kifaru 1.0.180 → 1.0.181

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.
@@ -1324,9 +1324,30 @@
1324
1324
  <button class="tab" role="tab" data-tab="audit" aria-selected="false">
1325
1325
  <span class="num">4</span> Audit Evidence
1326
1326
  </button>
1327
- <div class="session-picker" style="margin-left: auto; display: inline-flex; align-items: center; gap: 8px; padding: 6px 0;">
1328
- <label for="globalSessionSelect" class="eyebrow" style="font-size: 11px; margin: 0; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted);">Agent Session:</label>
1329
- <select id="globalSessionSelect" style="background: var(--surface-2, #18202b); color: var(--ink, #e6edf3); border: 1px solid var(--border, #293039); border-radius: 6px; padding: 4px 8px; font-size: 12px; font-family: var(--font-mono, monospace); max-width: 380px; cursor: pointer;">
1327
+ <div
1328
+ class="session-picker"
1329
+ style="margin-left: auto; display: inline-flex; align-items: center; gap: 8px; padding: 6px 0"
1330
+ >
1331
+ <label
1332
+ for="globalSessionSelect"
1333
+ class="eyebrow"
1334
+ style="font-size: 11px; margin: 0; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted)"
1335
+ >Agent Session:</label
1336
+ >
1337
+ <select
1338
+ id="globalSessionSelect"
1339
+ style="
1340
+ background: var(--surface-2, #18202b);
1341
+ color: var(--ink, #e6edf3);
1342
+ border: 1px solid var(--border, #293039);
1343
+ border-radius: 6px;
1344
+ padding: 4px 8px;
1345
+ font-size: 12px;
1346
+ font-family: var(--font-mono, monospace);
1347
+ max-width: 380px;
1348
+ cursor: pointer;
1349
+ "
1350
+ >
1330
1351
  <option value="auto">⚡ Latest Session (Auto)</option>
1331
1352
  <option value="all">🌐 All Workspace Sessions</option>
1332
1353
  </select>
@@ -1381,12 +1402,12 @@
1381
1402
  <div class="flist" id="topfindings"></div>
1382
1403
  </div>
1383
1404
  </div>
1384
- <div class="card" id="overviewRecentRunsCard" style="margin-top: 14px; display: none;">
1405
+ <div class="card" id="overviewRecentRunsCard" style="margin-top: 14px; display: none">
1385
1406
  <div class="card-h">
1386
1407
  <h2>Recent agent sessions &amp; runs</h2>
1387
1408
  <span class="sub" id="overviewRunsCount">Durable platform ledger</span>
1388
1409
  </div>
1389
- <div id="overviewRunsList" style="display:flex; flex-direction:column; gap:8px;"></div>
1410
+ <div id="overviewRunsList" style="display: flex; flex-direction: column; gap: 8px"></div>
1390
1411
  </div>
1391
1412
  </section>
1392
1413
 
@@ -1400,7 +1421,10 @@
1400
1421
  </p>
1401
1422
  </div>
1402
1423
  <div class="card">
1403
- <div class="run-head" style="display:flex; justify-content:space-between; align-items:flex-start; flex-wrap:wrap; gap:12px;">
1424
+ <div
1425
+ class="run-head"
1426
+ style="display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 12px"
1427
+ >
1404
1428
  <div>
1405
1429
  <div class="eyebrow">Target</div>
1406
1430
  <div class="mono" id="runTarget" style="font-size: 14px; font-weight: 600; margin-top: 3px">
@@ -1410,15 +1434,42 @@
1410
1434
  Run <span class="mono">RUN-7F3A9C</span> · worker <span class="mono">kf-worker-nbo-02</span> ·
1411
1435
  authorization verified ✓
1412
1436
  </div>
1413
- <div style="margin-top: 8px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
1414
- <span class="eyebrow" style="font-size: 10px;">Select Run / Session:</span>
1415
- <select id="runSelect" style="background: var(--surface-2, #18202b); color: var(--ink, #e6edf3); border: 1px solid var(--border, #293039); border-radius: 6px; padding: 4px 8px; font-size: 12px; font-family: var(--font-mono, monospace); max-width: 480px; cursor: pointer;">
1437
+ <div style="margin-top: 8px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap">
1438
+ <span class="eyebrow" style="font-size: 10px">Select Run / Session:</span>
1439
+ <select
1440
+ id="runSelect"
1441
+ style="
1442
+ background: var(--surface-2, #18202b);
1443
+ color: var(--ink, #e6edf3);
1444
+ border: 1px solid var(--border, #293039);
1445
+ border-radius: 6px;
1446
+ padding: 4px 8px;
1447
+ font-size: 12px;
1448
+ font-family: var(--font-mono, monospace);
1449
+ max-width: 480px;
1450
+ cursor: pointer;
1451
+ "
1452
+ >
1416
1453
  <option value="auto">⚡ Auto-follow (Latest / In-Flight)</option>
1417
1454
  </select>
1418
1455
  </div>
1419
1456
  </div>
1420
- <div style="display:flex; gap:8px; align-items:center;">
1421
- <a href="/agent" target="_blank" class="btn" style="text-decoration:none; font-size:12px; padding:6px 12px; background:var(--surface-2); border:1px solid var(--border); color:var(--ink-2); border-radius:8px;">Open Agent View ↗</a>
1457
+ <div style="display: flex; gap: 8px; align-items: center">
1458
+ <a
1459
+ href="/agent"
1460
+ target="_blank"
1461
+ class="btn"
1462
+ style="
1463
+ text-decoration: none;
1464
+ font-size: 12px;
1465
+ padding: 6px 12px;
1466
+ background: var(--surface-2);
1467
+ border: 1px solid var(--border);
1468
+ color: var(--ink-2);
1469
+ border-radius: 8px;
1470
+ "
1471
+ >Open Agent View ↗</a
1472
+ >
1422
1473
  <button class="btn btn-primary" id="runBtn">
1423
1474
  <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z" /></svg
1424
1475
  ><span id="runBtnLabel">Run assessment</span>
@@ -2309,7 +2360,9 @@ ${f.dpa.map((d) => " - " + d).join("\n")}`
2309
2360
  if (metaEl) {
2310
2361
  const worker = run.workerId || run.source || (run.runtime ? `runtime ${run.runtime}` : "kf-worker-local")
2311
2362
  const auth = isLive ? "turn in flight · active hunting" : "authorization verified ✓"
2312
- const sessionPart = run.sessionId ? ` · session <span class="mono" style="color:var(--accent); font-weight:600">${run.sessionId}</span>` : ""
2363
+ const sessionPart = run.sessionId
2364
+ ? ` · session <span class="mono" style="color:var(--accent); font-weight:600">${run.sessionId}</span>`
2365
+ : ""
2313
2366
  const wsPart = run.workspaceId ? ` · ws <span class="mono">${run.workspaceId}</span>` : ""
2314
2367
  metaEl.innerHTML = `Run <span class="mono">${run.id}</span>${sessionPart}${wsPart} · worker <span class="mono">${worker}</span> · ${auth}`
2315
2368
  }
@@ -2722,7 +2775,9 @@ ${f.dpa.map((d) => " - " + d).join("\n")}`
2722
2775
  label: `${statusIcon} ${shortTitle} · ${shortId} (${countLabel})`,
2723
2776
  })
2724
2777
  }
2725
- const currentOpts = Array.from(select.options).map((o) => o.value).join(",")
2778
+ const currentOpts = Array.from(select.options)
2779
+ .map((o) => o.value)
2780
+ .join(",")
2726
2781
  const newOpts = opts.map((o) => o.val).join(",")
2727
2782
  if (currentOpts !== newOpts) {
2728
2783
  select.innerHTML = ""
@@ -2746,16 +2801,22 @@ ${f.dpa.map((d) => " - " + d).join("\n")}`
2746
2801
  const opts = [{ val: "auto", label: "⚡ Auto-follow (Latest / In-Flight)" }]
2747
2802
  for (const r of runs) {
2748
2803
  const status = r.status ?? r.state ?? "unknown"
2749
- const icon = ["running", "leased", "queued"].includes(status) ? "● [RUNNING]" : ["completed", "succeeded"].includes(status) ? "✓" : "✗"
2804
+ const icon = ["running", "leased", "queued"].includes(status)
2805
+ ? "● [RUNNING]"
2806
+ : ["completed", "succeeded"].includes(status)
2807
+ ? "✓"
2808
+ : "✗"
2750
2809
  const shortId = r.id.length > 20 ? `${r.id.slice(0, 16)}…` : r.id
2751
2810
  const shortTitle = (r.title || r.id).slice(0, 36)
2752
2811
  const sessionSuffix = r.sessionId ? ` [${r.sessionId.slice(0, 10)}…]` : ""
2753
2812
  opts.push({
2754
2813
  val: r.id,
2755
- label: `${icon} ${shortTitle} · ${shortId}${sessionSuffix}`
2814
+ label: `${icon} ${shortTitle} · ${shortId}${sessionSuffix}`,
2756
2815
  })
2757
2816
  }
2758
- const currentOpts = Array.from(select.options).map((o) => o.value).join(",")
2817
+ const currentOpts = Array.from(select.options)
2818
+ .map((o) => o.value)
2819
+ .join(",")
2759
2820
  const newOpts = opts.map((o) => o.val).join(",")
2760
2821
  if (currentOpts !== newOpts) {
2761
2822
  select.innerHTML = ""
@@ -2783,13 +2844,15 @@ ${f.dpa.map((d) => " - " + d).join("\n")}`
2783
2844
  }
2784
2845
  card.style.display = "block"
2785
2846
  if (count) count.textContent = `${runs.length} recorded run${runs.length === 1 ? "" : "s"} in workspace`
2786
- list.innerHTML = runs.slice(0, 8).map((r) => {
2787
- const status = r.status ?? r.state ?? "unknown"
2788
- const isLive = ["running", "queued", "leased"].includes(status)
2789
- const isOk = ["completed", "succeeded"].includes(status)
2790
- const badgeClass = isLive ? "sevtag sev-low" : isOk ? "statuspill" : "sevtag sev-critical"
2791
- const timeStr = r.updatedAt ? new Date(r.updatedAt).toLocaleTimeString() : ""
2792
- return `<div style="display:flex; justify-content:space-between; align-items:center; padding:8px 12px; background:var(--surface-2); border-radius:8px; border:1px solid var(--hair); font-size:12.5px;">
2847
+ list.innerHTML = runs
2848
+ .slice(0, 8)
2849
+ .map((r) => {
2850
+ const status = r.status ?? r.state ?? "unknown"
2851
+ const isLive = ["running", "queued", "leased"].includes(status)
2852
+ const isOk = ["completed", "succeeded"].includes(status)
2853
+ const badgeClass = isLive ? "sevtag sev-low" : isOk ? "statuspill" : "sevtag sev-critical"
2854
+ const timeStr = r.updatedAt ? new Date(r.updatedAt).toLocaleTimeString() : ""
2855
+ return `<div style="display:flex; justify-content:space-between; align-items:center; padding:8px 12px; background:var(--surface-2); border-radius:8px; border:1px solid var(--hair); font-size:12.5px;">
2793
2856
  <div style="display:flex; align-items:center; gap:10px; min-width:0; overflow:hidden;">
2794
2857
  <span class="${badgeClass}">${status.toUpperCase()}</span>
2795
2858
  <span style="font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${r.title || r.id}</span>
@@ -2801,7 +2864,8 @@ ${f.dpa.map((d) => " - " + d).join("\n")}`
2801
2864
  <button class="btn btn-sm" onclick="inspectRun('${r.id}')" style="font-size:11px; padding:3px 9px;">Inspect Run &rarr;</button>
2802
2865
  </div>
2803
2866
  </div>`
2804
- }).join("")
2867
+ })
2868
+ .join("")
2805
2869
  }
2806
2870
 
2807
2871
  async function inspectRun(runId) {
@@ -2967,10 +3031,9 @@ ${f.dpa.map((d) => " - " + d).join("\n")}`
2967
3031
  $("#srcPill").className = "src live"
2968
3032
  $("#srcText").textContent = "Live · platform DB"
2969
3033
  $("#srcPill").title = "Live — click to manage sign-in."
2970
- const sessionFlag = effectiveSessionId
2971
- ? ` · session ${effectiveSessionId.slice(0, 16)}…`
2972
- : " · all sessions"
2973
- $("#demoFlag").textContent = "● Live — " + total + " findings across " + runs + " runs" + sessionFlag + " · updated " + ago
3034
+ const sessionFlag = effectiveSessionId ? ` · session ${effectiveSessionId.slice(0, 16)}…` : " · all sessions"
3035
+ $("#demoFlag").textContent =
3036
+ "● Live — " + total + " findings across " + runs + " runs" + sessionFlag + " · updated " + ago
2974
3037
  const footFindings = effectiveSessionId
2975
3038
  ? `/api/v1/findings?sessionId=${effectiveSessionId.slice(0, 12)}…`
2976
3039
  : "/api/v1/findings"
package/kifaru-pi.js CHANGED
@@ -214,7 +214,12 @@ var init_structured_tools = __esm(() => {
214
214
  SEVERITY = Type.Union([Type.Literal("info"), Type.Literal("low"), Type.Literal("medium"), Type.Literal("high"), Type.Literal("critical")], { description: "Finding severity band." });
215
215
  DISPOSITION = Type.Union([Type.Literal("candidate"), Type.Literal("confirmed"), Type.Literal("refuted"), Type.Literal("inconclusive")], { description: "Confidence in the finding. Candidates never affect client posture until confirmed." });
216
216
  STATUS = Type.Union([Type.Literal("succeeded"), Type.Literal("blocked"), Type.Literal("inconclusive"), Type.Literal("failed")], { description: "Terminal state of the stage." });
217
- STRUCTURED_TOOL_NAMES = ["submit_finding", "record_evidence", "record_negative_control", "stage_complete"];
217
+ STRUCTURED_TOOL_NAMES = [
218
+ "submit_finding",
219
+ "record_evidence",
220
+ "record_negative_control",
221
+ "stage_complete"
222
+ ];
218
223
  });
219
224
  // ../core/src/model/model-family.ts
220
225
  function getModelFamily(model) {
@@ -2213,6 +2218,125 @@ var init_embedded_skills = __esm(() => {
2213
2218
  init_embedded_skills_generated();
2214
2219
  });
2215
2220
 
2221
+ // ../core/src/theme/embedded-theme.ts
2222
+ import fs4 from "fs";
2223
+ import os4 from "os";
2224
+ import path4 from "path";
2225
+ function kifaruThemesRoot() {
2226
+ if (process.env.KIFARU_THEMES_DIR)
2227
+ return path4.resolve(process.env.KIFARU_THEMES_DIR);
2228
+ const xdg = process.env.XDG_DATA_HOME || path4.join(os4.homedir(), ".local", "share");
2229
+ return path4.join(xdg, "kifaru", "themes");
2230
+ }
2231
+ function materializeKifaruThemes(root = kifaruThemesRoot()) {
2232
+ const file = path4.join(root, `${KIFARU_THEME_NAME}.json`);
2233
+ const content = `${JSON.stringify(EMBEDDED_KIFARU_THEME, null, 2)}
2234
+ `;
2235
+ try {
2236
+ const existing = fs4.existsSync(file) ? fs4.readFileSync(file, "utf8") : undefined;
2237
+ if (existing !== content) {
2238
+ fs4.mkdirSync(root, { recursive: true });
2239
+ fs4.writeFileSync(file, content);
2240
+ }
2241
+ return root;
2242
+ } catch {
2243
+ return null;
2244
+ }
2245
+ }
2246
+ var KIFARU_THEME_NAME = "kifaru-dark", EMBEDDED_KIFARU_THEME;
2247
+ var init_embedded_theme = __esm(() => {
2248
+ EMBEDDED_KIFARU_THEME = {
2249
+ $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2250
+ name: KIFARU_THEME_NAME,
2251
+ vars: {
2252
+ accent: "#5a90c2",
2253
+ accentInk: "#82abd6",
2254
+ ink2: "#a7aeb8",
2255
+ muted: "#6e767f",
2256
+ hair: "#222831",
2257
+ border: "#293039",
2258
+ raised: "#1a2027",
2259
+ surface2: "#1c222a",
2260
+ accentSoft: "#18232f",
2261
+ s6: "#305d84",
2262
+ s5: "#4574a3",
2263
+ crit: "#cf5a55",
2264
+ high: "#c58a48",
2265
+ med: "#bda23c",
2266
+ good: "#4aa66a",
2267
+ low: "#5b93cb",
2268
+ info: "#8b929b",
2269
+ critBg: "#33201f",
2270
+ highBg: "#312a1c",
2271
+ medBg: "#2e2915",
2272
+ lowBg: "#16222f",
2273
+ infoBg: "#22262b",
2274
+ goodBg: "#152a1d"
2275
+ },
2276
+ colors: {
2277
+ accent: "accent",
2278
+ border: "border",
2279
+ borderAccent: "accentInk",
2280
+ borderMuted: "hair",
2281
+ success: "good",
2282
+ error: "crit",
2283
+ warning: "high",
2284
+ muted: "ink2",
2285
+ dim: "muted",
2286
+ text: "",
2287
+ thinkingText: "ink2",
2288
+ selectedBg: "surface2",
2289
+ scrollbarTrack: "hair",
2290
+ scrollbarThumb: "muted",
2291
+ userMessageBg: "raised",
2292
+ userMessageText: "",
2293
+ customMessageBg: "accentSoft",
2294
+ customMessageText: "",
2295
+ customMessageLabel: "accent",
2296
+ toolPendingBg: "infoBg",
2297
+ toolSuccessBg: "goodBg",
2298
+ toolErrorBg: "critBg",
2299
+ toolTitle: "accentInk",
2300
+ toolOutput: "",
2301
+ mdHeading: "accentInk",
2302
+ mdLink: "accent",
2303
+ mdLinkUrl: "muted",
2304
+ mdCode: "low",
2305
+ mdCodeBlock: "",
2306
+ mdCodeBlockBorder: "border",
2307
+ mdQuote: "ink2",
2308
+ mdQuoteBorder: "border",
2309
+ mdHr: "hair",
2310
+ mdListBullet: "low",
2311
+ toolDiffAdded: "good",
2312
+ toolDiffRemoved: "crit",
2313
+ toolDiffContext: "muted",
2314
+ syntaxComment: "muted",
2315
+ syntaxKeyword: "accent",
2316
+ syntaxFunction: "accentInk",
2317
+ syntaxVariable: "high",
2318
+ syntaxString: "good",
2319
+ syntaxNumber: "med",
2320
+ syntaxType: "low",
2321
+ syntaxOperator: "accent",
2322
+ syntaxPunctuation: "ink2",
2323
+ thinkingOff: "muted",
2324
+ thinkingMinimal: "s6",
2325
+ thinkingLow: "s5",
2326
+ thinkingMedium: "accent",
2327
+ thinkingHigh: "accentInk",
2328
+ thinkingXhigh: "high",
2329
+ thinkingMax: "crit",
2330
+ bashMode: "med"
2331
+ },
2332
+ export: {
2333
+ pageBg: "#0d1013",
2334
+ cardBg: "#151a1f",
2335
+ infoBg: "#1c222a"
2336
+ }
2337
+ };
2338
+ });
2339
+
2216
2340
  // ../core/src/model/router-deps.ts
2217
2341
  function makeLogger(base) {
2218
2342
  const format = (message, extra) => {
@@ -3076,10 +3200,10 @@ function mergeDefs(...defs) {
3076
3200
  function cloneDef(schema) {
3077
3201
  return mergeDefs(schema._zod.def);
3078
3202
  }
3079
- function getElementAtPath(obj, path4) {
3080
- if (!path4)
3203
+ function getElementAtPath(obj, path5) {
3204
+ if (!path5)
3081
3205
  return obj;
3082
- return path4.reduce((acc, key) => acc?.[key], obj);
3206
+ return path5.reduce((acc, key) => acc?.[key], obj);
3083
3207
  }
3084
3208
  function promiseAllObject(promisesObj) {
3085
3209
  const keys = Object.keys(promisesObj);
@@ -3390,11 +3514,11 @@ function aborted(x, startIndex = 0) {
3390
3514
  }
3391
3515
  return false;
3392
3516
  }
3393
- function prefixIssues(path4, issues) {
3517
+ function prefixIssues(path5, issues) {
3394
3518
  return issues.map((iss) => {
3395
3519
  var _a15;
3396
3520
  (_a15 = iss).path ?? (_a15.path = []);
3397
- iss.path.unshift(path4);
3521
+ iss.path.unshift(path5);
3398
3522
  return iss;
3399
3523
  });
3400
3524
  }
@@ -3632,7 +3756,7 @@ function formatError(error, mapper = (issue2) => issue2.message) {
3632
3756
  }
3633
3757
  function treeifyError(error, mapper = (issue2) => issue2.message) {
3634
3758
  const result = { errors: [] };
3635
- const processError = (error2, path4 = []) => {
3759
+ const processError = (error2, path5 = []) => {
3636
3760
  var _a15, _b15;
3637
3761
  for (const issue2 of error2.issues) {
3638
3762
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -3642,7 +3766,7 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
3642
3766
  } else if (issue2.code === "invalid_element") {
3643
3767
  processError({ issues: issue2.issues }, issue2.path);
3644
3768
  } else {
3645
- const fullpath = [...path4, ...issue2.path];
3769
+ const fullpath = [...path5, ...issue2.path];
3646
3770
  if (fullpath.length === 0) {
3647
3771
  result.errors.push(mapper(issue2));
3648
3772
  continue;
@@ -3674,8 +3798,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
3674
3798
  }
3675
3799
  function toDotPath(_path) {
3676
3800
  const segs = [];
3677
- const path4 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
3678
- for (const seg of path4) {
3801
+ const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
3802
+ for (const seg of path5) {
3679
3803
  if (typeof seg === "number")
3680
3804
  segs.push(`[${seg}]`);
3681
3805
  else if (typeof seg === "symbol")
@@ -15950,13 +16074,13 @@ function resolveRef(ref, ctx) {
15950
16074
  if (!ref.startsWith("#")) {
15951
16075
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
15952
16076
  }
15953
- const path4 = ref.slice(1).split("/").filter(Boolean);
15954
- if (path4.length === 0) {
16077
+ const path5 = ref.slice(1).split("/").filter(Boolean);
16078
+ if (path5.length === 0) {
15955
16079
  return ctx.rootSchema;
15956
16080
  }
15957
16081
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
15958
- if (path4[0] === defsKey) {
15959
- const key = path4[1];
16082
+ if (path5[0] === defsKey) {
16083
+ const key = path5[1];
15960
16084
  if (!key || !ctx.defs[key]) {
15961
16085
  throw new Error(`Reference not found: ${ref}`);
15962
16086
  }
@@ -17138,8 +17262,8 @@ class ParseStatus {
17138
17262
  }
17139
17263
  }
17140
17264
  var makeIssue = (params) => {
17141
- const { data, path: path4, errorMaps, issueData } = params;
17142
- const fullPath = [...path4, ...issueData.path || []];
17265
+ const { data, path: path5, errorMaps, issueData } = params;
17266
+ const fullPath = [...path5, ...issueData.path || []];
17143
17267
  const fullIssue = {
17144
17268
  ...issueData,
17145
17269
  path: fullPath
@@ -17184,11 +17308,11 @@ var init_errorUtil = __esm(() => {
17184
17308
 
17185
17309
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v3/types.js
17186
17310
  class ParseInputLazyPath {
17187
- constructor(parent, value, path4, key) {
17311
+ constructor(parent, value, path5, key) {
17188
17312
  this._cachedPath = [];
17189
17313
  this.parent = parent;
17190
17314
  this.data = value;
17191
- this._path = path4;
17315
+ this._path = path5;
17192
17316
  this._key = key;
17193
17317
  }
17194
17318
  get path() {
@@ -22809,23 +22933,23 @@ var require_auth_config = __commonJS((exports, module) => {
22809
22933
  writeAuthConfig: () => writeAuthConfig
22810
22934
  });
22811
22935
  module.exports = __toCommonJS(auth_config_exports);
22812
- var fs4 = __toESM2(__require("fs"));
22813
- var path4 = __toESM2(__require("path"));
22936
+ var fs5 = __toESM2(__require("fs"));
22937
+ var path5 = __toESM2(__require("path"));
22814
22938
  var import_token_util = require_token_util();
22815
22939
  function getAuthConfigPath() {
22816
22940
  const dataDir = (0, import_token_util.getVercelDataDir)();
22817
22941
  if (!dataDir) {
22818
22942
  throw new Error(`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`);
22819
22943
  }
22820
- return path4.join(dataDir, "auth.json");
22944
+ return path5.join(dataDir, "auth.json");
22821
22945
  }
22822
22946
  function readAuthConfig() {
22823
22947
  try {
22824
22948
  const authPath = getAuthConfigPath();
22825
- if (!fs4.existsSync(authPath)) {
22949
+ if (!fs5.existsSync(authPath)) {
22826
22950
  return null;
22827
22951
  }
22828
- const content = fs4.readFileSync(authPath, "utf8");
22952
+ const content = fs5.readFileSync(authPath, "utf8");
22829
22953
  if (!content) {
22830
22954
  return null;
22831
22955
  }
@@ -22836,11 +22960,11 @@ var require_auth_config = __commonJS((exports, module) => {
22836
22960
  }
22837
22961
  function writeAuthConfig(config2) {
22838
22962
  const authPath = getAuthConfigPath();
22839
- const authDir = path4.dirname(authPath);
22840
- if (!fs4.existsSync(authDir)) {
22841
- fs4.mkdirSync(authDir, { mode: 504, recursive: true });
22963
+ const authDir = path5.dirname(authPath);
22964
+ if (!fs5.existsSync(authDir)) {
22965
+ fs5.mkdirSync(authDir, { mode: 504, recursive: true });
22842
22966
  }
22843
- fs4.writeFileSync(authPath, JSON.stringify(config2, null, 2), { mode: 384 });
22967
+ fs5.writeFileSync(authPath, JSON.stringify(config2, null, 2), { mode: 384 });
22844
22968
  }
22845
22969
  function isValidAccessToken(authConfig, expirationBufferMs = 0) {
22846
22970
  if (!authConfig.token)
@@ -23015,8 +23139,8 @@ var require_token_util = __commonJS((exports, module) => {
23015
23139
  saveToken: () => saveToken
23016
23140
  });
23017
23141
  module.exports = __toCommonJS(token_util_exports);
23018
- var path4 = __toESM2(__require("path"));
23019
- var fs4 = __toESM2(__require("fs"));
23142
+ var path5 = __toESM2(__require("path"));
23143
+ var fs5 = __toESM2(__require("fs"));
23020
23144
  var import_token_error = require_token_error();
23021
23145
  var import_token_io = require_token_io();
23022
23146
  var import_auth_config = require_auth_config();
@@ -23028,7 +23152,7 @@ var require_token_util = __commonJS((exports, module) => {
23028
23152
  if (!dataDir) {
23029
23153
  return null;
23030
23154
  }
23031
- return path4.join(dataDir, vercelFolder);
23155
+ return path5.join(dataDir, vercelFolder);
23032
23156
  }
23033
23157
  async function getVercelToken2(options) {
23034
23158
  const authConfig = (0, import_auth_config.readAuthConfig)();
@@ -23096,11 +23220,11 @@ var require_token_util = __commonJS((exports, module) => {
23096
23220
  if (!dir) {
23097
23221
  throw new import_token_error.VercelOidcTokenError("Unable to find project root directory. Have you linked your project with `vc link?`");
23098
23222
  }
23099
- const prjPath = path4.join(dir, ".vercel", "project.json");
23100
- if (!fs4.existsSync(prjPath)) {
23223
+ const prjPath = path5.join(dir, ".vercel", "project.json");
23224
+ if (!fs5.existsSync(prjPath)) {
23101
23225
  throw new import_token_error.VercelOidcTokenError("project.json not found, have you linked your project with `vc link?`");
23102
23226
  }
23103
- const prj = JSON.parse(fs4.readFileSync(prjPath, "utf8"));
23227
+ const prj = JSON.parse(fs5.readFileSync(prjPath, "utf8"));
23104
23228
  if (typeof prj.projectId !== "string" && typeof prj.orgId !== "string") {
23105
23229
  throw new TypeError("Expected a string-valued projectId property. Try running `vc link` to re-link your project.");
23106
23230
  }
@@ -23111,11 +23235,11 @@ var require_token_util = __commonJS((exports, module) => {
23111
23235
  if (!dir) {
23112
23236
  throw new import_token_error.VercelOidcTokenError("Unable to find user data directory. Please reach out to Vercel support.");
23113
23237
  }
23114
- const tokenPath = path4.join(dir, "com.vercel.token", `${projectId}.json`);
23238
+ const tokenPath = path5.join(dir, "com.vercel.token", `${projectId}.json`);
23115
23239
  const tokenJson = JSON.stringify(token);
23116
- fs4.mkdirSync(path4.dirname(tokenPath), { mode: 504, recursive: true });
23117
- fs4.writeFileSync(tokenPath, tokenJson);
23118
- fs4.chmodSync(tokenPath, 432);
23240
+ fs5.mkdirSync(path5.dirname(tokenPath), { mode: 504, recursive: true });
23241
+ fs5.writeFileSync(tokenPath, tokenJson);
23242
+ fs5.chmodSync(tokenPath, 432);
23119
23243
  return;
23120
23244
  }
23121
23245
  function loadToken(projectId) {
@@ -23123,11 +23247,11 @@ var require_token_util = __commonJS((exports, module) => {
23123
23247
  if (!dir) {
23124
23248
  throw new import_token_error.VercelOidcTokenError("Unable to find user data directory. Please reach out to Vercel support.");
23125
23249
  }
23126
- const tokenPath = path4.join(dir, "com.vercel.token", `${projectId}.json`);
23127
- if (!fs4.existsSync(tokenPath)) {
23250
+ const tokenPath = path5.join(dir, "com.vercel.token", `${projectId}.json`);
23251
+ if (!fs5.existsSync(tokenPath)) {
23128
23252
  return null;
23129
23253
  }
23130
- const token = JSON.parse(fs4.readFileSync(tokenPath, "utf8"));
23254
+ const token = JSON.parse(fs5.readFileSync(tokenPath, "utf8"));
23131
23255
  assertVercelOidcTokenResponse(token);
23132
23256
  return token;
23133
23257
  }
@@ -33644,6 +33768,7 @@ var init_src = __esm(() => {
33644
33768
  init_skill_loader();
33645
33769
  init_governed_skill_tool();
33646
33770
  init_embedded_skills();
33771
+ init_embedded_theme();
33647
33772
  });
33648
33773
 
33649
33774
  // ../headless-runtime/src/policy-gate.ts
@@ -33984,10 +34109,10 @@ function mergeDefs2(...defs) {
33984
34109
  function cloneDef2(schema) {
33985
34110
  return mergeDefs2(schema._zod.def);
33986
34111
  }
33987
- function getElementAtPath2(obj, path4) {
33988
- if (!path4)
34112
+ function getElementAtPath2(obj, path5) {
34113
+ if (!path5)
33989
34114
  return obj;
33990
- return path4.reduce((acc, key) => acc?.[key], obj);
34115
+ return path5.reduce((acc, key) => acc?.[key], obj);
33991
34116
  }
33992
34117
  function promiseAllObject2(promisesObj) {
33993
34118
  const keys = Object.keys(promisesObj);
@@ -34276,11 +34401,11 @@ function aborted2(x, startIndex = 0) {
34276
34401
  }
34277
34402
  return false;
34278
34403
  }
34279
- function prefixIssues2(path4, issues) {
34404
+ function prefixIssues2(path5, issues) {
34280
34405
  return issues.map((iss) => {
34281
34406
  var _a21;
34282
34407
  (_a21 = iss).path ?? (_a21.path = []);
34283
- iss.path.unshift(path4);
34408
+ iss.path.unshift(path5);
34284
34409
  return iss;
34285
34410
  });
34286
34411
  }
@@ -34503,7 +34628,7 @@ function treeifyError2(error48, _mapper) {
34503
34628
  return issue3.message;
34504
34629
  };
34505
34630
  const result = { errors: [] };
34506
- const processError = (error49, path4 = []) => {
34631
+ const processError = (error49, path5 = []) => {
34507
34632
  var _a21, _b16;
34508
34633
  for (const issue3 of error49.issues) {
34509
34634
  if (issue3.code === "invalid_union" && issue3.errors.length) {
@@ -34513,7 +34638,7 @@ function treeifyError2(error48, _mapper) {
34513
34638
  } else if (issue3.code === "invalid_element") {
34514
34639
  processError({ issues: issue3.issues }, issue3.path);
34515
34640
  } else {
34516
- const fullpath = [...path4, ...issue3.path];
34641
+ const fullpath = [...path5, ...issue3.path];
34517
34642
  if (fullpath.length === 0) {
34518
34643
  result.errors.push(mapper(issue3));
34519
34644
  continue;
@@ -34545,8 +34670,8 @@ function treeifyError2(error48, _mapper) {
34545
34670
  }
34546
34671
  function toDotPath2(_path) {
34547
34672
  const segs = [];
34548
- const path4 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
34549
- for (const seg of path4) {
34673
+ const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
34674
+ for (const seg of path5) {
34550
34675
  if (typeof seg === "number")
34551
34676
  segs.push(`[${seg}]`);
34552
34677
  else if (typeof seg === "symbol")
@@ -47927,14 +48052,14 @@ var init_event_sink = __esm(() => {
47927
48052
  });
47928
48053
 
47929
48054
  // ../headless-runtime/src/sqlite-event-store.ts
47930
- import fs4 from "fs";
47931
- import path4 from "path";
48055
+ import fs5 from "fs";
48056
+ import path5 from "path";
47932
48057
  import { Database } from "bun:sqlite";
47933
48058
 
47934
48059
  class SqliteEventStore {
47935
48060
  db;
47936
48061
  constructor(dbPath) {
47937
- fs4.mkdirSync(path4.dirname(dbPath), { recursive: true });
48062
+ fs5.mkdirSync(path5.dirname(dbPath), { recursive: true });
47938
48063
  this.db = new Database(dbPath, { create: true });
47939
48064
  this.initialize();
47940
48065
  }
@@ -48223,20 +48348,20 @@ var init_src3 = __esm(() => {
48223
48348
  });
48224
48349
 
48225
48350
  // ../execution-runtime/src/paths.ts
48226
- import os4 from "os";
48227
- import path6 from "path";
48351
+ import os5 from "os";
48352
+ import path7 from "path";
48228
48353
  function runtimeDataDir(env = process.env, platform = process.platform) {
48229
48354
  const clean = (value) => value?.replace(/[\x00-\x1f]/g, "");
48230
- const home = env.HOME?.includes("/snap/") ? clean(env.XDG_CONFIG_HOME)?.replace(/\/\.config$/, "") || os4.homedir() : os4.homedir();
48231
- return platform === "win32" ? path6.join(clean(env.LOCALAPPDATA) || path6.join(home, "AppData", "Local"), "kifaru", "data") : path6.join(clean(env.XDG_DATA_HOME) || path6.join(home, ".local", "share"), "kifaru");
48355
+ const home = env.HOME?.includes("/snap/") ? clean(env.XDG_CONFIG_HOME)?.replace(/\/\.config$/, "") || os5.homedir() : os5.homedir();
48356
+ return platform === "win32" ? path7.join(clean(env.LOCALAPPDATA) || path7.join(home, "AppData", "Local"), "kifaru", "data") : path7.join(clean(env.XDG_DATA_HOME) || path7.join(home, ".local", "share"), "kifaru");
48232
48357
  }
48233
48358
  var init_paths = () => {};
48234
48359
 
48235
48360
  // ../execution-runtime/src/python.ts
48236
48361
  import { createHash } from "crypto";
48237
- import fs6 from "fs/promises";
48362
+ import fs7 from "fs/promises";
48238
48363
  import { accessSync, constants as fsConstants } from "fs";
48239
- import path7 from "path";
48364
+ import path8 from "path";
48240
48365
  var PythonRuntime;
48241
48366
  var init_python = __esm(() => {
48242
48367
  init_paths();
@@ -48330,10 +48455,10 @@ var init_python = __esm(() => {
48330
48455
  clearTimeout(timer);
48331
48456
  return { exitCode, stdout, stderr };
48332
48457
  },
48333
- fileExists: (filepath) => fs6.stat(filepath).then(() => true).catch(() => false),
48334
- readFile: (filepath) => fs6.readFile(filepath, "utf8"),
48335
- writeFile: (filepath, content) => fs6.writeFile(filepath, content),
48336
- mkdir: (filepath) => fs6.mkdir(filepath, { recursive: true }).then(() => {
48458
+ fileExists: (filepath) => fs7.stat(filepath).then(() => true).catch(() => false),
48459
+ readFile: (filepath) => fs7.readFile(filepath, "utf8"),
48460
+ writeFile: (filepath, content) => fs7.writeFile(filepath, content),
48461
+ mkdir: (filepath) => fs7.mkdir(filepath, { recursive: true }).then(() => {
48337
48462
  return;
48338
48463
  }),
48339
48464
  platform: process.platform,
@@ -48363,35 +48488,35 @@ var init_python = __esm(() => {
48363
48488
  }
48364
48489
  PythonRuntime.lockHash = lockHash;
48365
48490
  function managedRoot(dataDir = runtimeDataDir()) {
48366
- return path7.join(dataDir, "python");
48491
+ return path8.join(dataDir, "python");
48367
48492
  }
48368
48493
  PythonRuntime.managedRoot = managedRoot;
48369
48494
  function managedVenvPath(profile, dataDir = runtimeDataDir()) {
48370
- return path7.join(managedRoot(dataDir), profile);
48495
+ return path8.join(managedRoot(dataDir), profile);
48371
48496
  }
48372
48497
  PythonRuntime.managedVenvPath = managedVenvPath;
48373
48498
  function venvBinDir(venvPath, platform = process.platform) {
48374
- return platform === "win32" ? path7.join(venvPath, "Scripts") : path7.join(venvPath, "bin");
48499
+ return platform === "win32" ? path8.join(venvPath, "Scripts") : path8.join(venvPath, "bin");
48375
48500
  }
48376
48501
  PythonRuntime.venvBinDir = venvBinDir;
48377
48502
  function venvPythonPath(venvPath, platform = process.platform) {
48378
- return platform === "win32" ? path7.join(venvPath, "Scripts", "python.exe") : path7.join(venvPath, "bin", "python");
48503
+ return platform === "win32" ? path8.join(venvPath, "Scripts", "python.exe") : path8.join(venvPath, "bin", "python");
48379
48504
  }
48380
48505
  PythonRuntime.venvPythonPath = venvPythonPath;
48381
48506
  function stampPath(profile, dataDir = runtimeDataDir()) {
48382
- return path7.join(managedVenvPath(profile, dataDir), ".kifaru-python.json");
48507
+ return path8.join(managedVenvPath(profile, dataDir), ".kifaru-python.json");
48383
48508
  }
48384
48509
  PythonRuntime.stampPath = stampPath;
48385
48510
  function prependPathOnce(env, dir) {
48386
- const parts = (env.PATH ?? "").split(path7.delimiter).filter(Boolean);
48387
- return { ...env, PATH: [dir, ...parts.filter((part) => part !== dir)].join(path7.delimiter) };
48511
+ const parts = (env.PATH ?? "").split(path8.delimiter).filter(Boolean);
48512
+ return { ...env, PATH: [dir, ...parts.filter((part) => part !== dir)].join(path8.delimiter) };
48388
48513
  }
48389
48514
  PythonRuntime.prependPathOnce = prependPathOnce;
48390
48515
  function candidateVenvs(cwd, env = process.env) {
48391
48516
  return [
48392
48517
  { source: "active_venv", path: env.VIRTUAL_ENV },
48393
- { source: "workspace_dotvenv", path: path7.join(cwd, ".venv") },
48394
- { source: "workspace_venv", path: path7.join(cwd, "venv") }
48518
+ { source: "workspace_dotvenv", path: path8.join(cwd, ".venv") },
48519
+ { source: "workspace_venv", path: path8.join(cwd, "venv") }
48395
48520
  ].filter((item) => Boolean(item.path));
48396
48521
  }
48397
48522
  PythonRuntime.candidateVenvs = candidateVenvs;
@@ -48417,11 +48542,11 @@ var init_python = __esm(() => {
48417
48542
  };
48418
48543
  if (settings.explicitPythonBin) {
48419
48544
  const selected = settings.explicitPythonBin;
48420
- const absolute = path7.isAbsolute(selected);
48545
+ const absolute = path8.isAbsolute(selected);
48421
48546
  return {
48422
48547
  ...base,
48423
48548
  selectedPython: selected,
48424
- selectedBinDir: path7.dirname(selected),
48549
+ selectedBinDir: path8.dirname(selected),
48425
48550
  source: "explicit",
48426
48551
  projectVenvActive: false,
48427
48552
  available: absolute && await deps2.fileExists(selected),
@@ -48457,7 +48582,7 @@ var init_python = __esm(() => {
48457
48582
  return {
48458
48583
  ...base,
48459
48584
  selectedPython: system,
48460
- selectedBinDir: system ? path7.dirname(system) : undefined,
48585
+ selectedBinDir: system ? path8.dirname(system) : undefined,
48461
48586
  source: system ? "system" : "missing",
48462
48587
  projectVenvActive: false,
48463
48588
  available: Boolean(system)
@@ -48471,8 +48596,8 @@ var init_python = __esm(() => {
48471
48596
  if (!settings.enabled)
48472
48597
  return [];
48473
48598
  const dirs = new Set;
48474
- if (settings.explicitPythonBin && path7.isAbsolute(settings.explicitPythonBin)) {
48475
- dirs.add(path7.dirname(settings.explicitPythonBin));
48599
+ if (settings.explicitPythonBin && path8.isAbsolute(settings.explicitPythonBin)) {
48600
+ dirs.add(path8.dirname(settings.explicitPythonBin));
48476
48601
  }
48477
48602
  for (const candidate of candidateVenvs(input.cwd, env)) {
48478
48603
  if (await deps2.fileExists(venvPythonPath(candidate.path, deps2.platform))) {
@@ -48626,7 +48751,7 @@ var init_python = __esm(() => {
48626
48751
  };
48627
48752
  const installer = uv ? "uv" : "venv-pip";
48628
48753
  try {
48629
- await deps2.mkdir(path7.dirname(paths.venvPath));
48754
+ await deps2.mkdir(path8.dirname(paths.venvPath));
48630
48755
  await deps2.writeFile(paths.lockPath, requirementsLock(settings.profile));
48631
48756
  if (uv) {
48632
48757
  if (needsVenv) {
@@ -48701,7 +48826,7 @@ ${result.stderr}`.trim().split(/\r?\n/).find((line) => line.trim().length > 0)?.
48701
48826
  }
48702
48827
  }
48703
48828
  async function writeStamp(filepath, stamp, deps2) {
48704
- await deps2.mkdir(path7.dirname(filepath));
48829
+ await deps2.mkdir(path8.dirname(filepath));
48705
48830
  await deps2.writeFile(filepath, JSON.stringify(stamp, null, 2) + `
48706
48831
  `);
48707
48832
  }
@@ -48712,7 +48837,7 @@ ${result.stderr}`.trim().split(/\r?\n/).find((line) => line.trim().length > 0)?.
48712
48837
  binDir: venvBinDir(venvPath, platform),
48713
48838
  pythonPath: venvPythonPath(venvPath, platform),
48714
48839
  stampPath: stampPath(profile, dataDir),
48715
- lockPath: path7.join(managedRoot(dataDir), `${profile}.requirements.lock`)
48840
+ lockPath: path8.join(managedRoot(dataDir), `${profile}.requirements.lock`)
48716
48841
  };
48717
48842
  }
48718
48843
  function whichInEnvironment(name21, env, platform) {
@@ -48721,10 +48846,10 @@ ${result.stderr}`.trim().split(/\r?\n/).find((line) => line.trim().length > 0)?.
48721
48846
  if (!pathValue)
48722
48847
  return Bun.which(name21);
48723
48848
  const extensions = platform === "win32" ? (env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean) : [""];
48724
- const hasExtension = platform === "win32" && path7.win32.extname(name21).length > 0;
48849
+ const hasExtension = platform === "win32" && path8.win32.extname(name21).length > 0;
48725
48850
  for (const dir of pathValue.split(separator).filter(Boolean)) {
48726
48851
  for (const extension of hasExtension ? [""] : extensions) {
48727
- const candidate = platform === "win32" ? path7.win32.join(dir, name21 + extension.toLowerCase()) : path7.join(dir, name21);
48852
+ const candidate = platform === "win32" ? path8.win32.join(dir, name21 + extension.toLowerCase()) : path8.join(dir, name21);
48728
48853
  try {
48729
48854
  accessSync(candidate, fsConstants.X_OK);
48730
48855
  return candidate;
@@ -48748,8 +48873,8 @@ ${result.stderr}`.trim().split(/\r?\n/).find((line) => line.trim().length > 0)?.
48748
48873
 
48749
48874
  // ../execution-runtime/src/python-helpers.ts
48750
48875
  import { createHash as createHash2 } from "crypto";
48751
- import fs7 from "fs/promises";
48752
- import path8 from "path";
48876
+ import fs8 from "fs/promises";
48877
+ import path9 from "path";
48753
48878
  var PythonHelpers;
48754
48879
  var init_python_helpers = __esm(() => {
48755
48880
  init_python();
@@ -48997,15 +49122,15 @@ if __name__ == "__main__":
48997
49122
  PythonHelpers.HUNT_MODULE_VERSION = createHash2("sha256").update(PythonHelpers.HUNT_MODULE_SOURCE).digest("hex").slice(0, 12);
48998
49123
  function defaultDeps() {
48999
49124
  return {
49000
- mkdir: (dir) => fs7.mkdir(dir, { recursive: true }).then(() => {
49125
+ mkdir: (dir) => fs8.mkdir(dir, { recursive: true }).then(() => {
49001
49126
  return;
49002
49127
  }),
49003
- readFile: (file3) => fs7.readFile(file3, "utf8"),
49004
- writeFile: (file3, content) => fs7.writeFile(file3, content)
49128
+ readFile: (file3) => fs8.readFile(file3, "utf8"),
49129
+ writeFile: (file3, content) => fs8.writeFile(file3, content)
49005
49130
  };
49006
49131
  }
49007
49132
  function helpersDir(dataDir = runtimeDataDir()) {
49008
- return path8.join(PythonRuntime.managedRoot(dataDir), "helpers");
49133
+ return path9.join(PythonRuntime.managedRoot(dataDir), "helpers");
49009
49134
  }
49010
49135
  PythonHelpers.helpersDir = helpersDir;
49011
49136
  const ensureTasks = new Map;
@@ -49015,8 +49140,8 @@ if __name__ == "__main__":
49015
49140
  if (cached3)
49016
49141
  return cached3;
49017
49142
  const task = (async () => {
49018
- const target = path8.join(dir, "hunt.py");
49019
- const stamp = path8.join(dir, ".hunt-version");
49143
+ const target = path9.join(dir, "hunt.py");
49144
+ const stamp = path9.join(dir, ".hunt-version");
49020
49145
  try {
49021
49146
  const [onDisk, current] = await Promise.all([
49022
49147
  deps2.readFile(target).catch(() => {
@@ -49037,8 +49162,8 @@ if __name__ == "__main__":
49037
49162
  }
49038
49163
  PythonHelpers.ensure = ensure;
49039
49164
  function prependPythonPath(env, dir) {
49040
- const parts = (env.PYTHONPATH ?? "").split(path8.delimiter).filter(Boolean);
49041
- return { ...env, PYTHONPATH: [dir, ...parts.filter((part) => part !== dir)].join(path8.delimiter) };
49165
+ const parts = (env.PYTHONPATH ?? "").split(path9.delimiter).filter(Boolean);
49166
+ return { ...env, PYTHONPATH: [dir, ...parts.filter((part) => part !== dir)].join(path9.delimiter) };
49042
49167
  }
49043
49168
  PythonHelpers.prependPythonPath = prependPythonPath;
49044
49169
  async function applyToEnv(env, dataDir = runtimeDataDir(), deps2 = defaultDeps()) {
@@ -49098,8 +49223,8 @@ var init_python_prompt = __esm(() => {
49098
49223
  });
49099
49224
 
49100
49225
  // ../execution-runtime/src/child-environment.ts
49101
- import os5 from "os";
49102
- import path9 from "path";
49226
+ import os6 from "os";
49227
+ import path10 from "path";
49103
49228
  var MODEL_PROVIDER_CREDENTIAL_ENV_VARS, ChildEnvironment;
49104
49229
  var init_child_environment = __esm(() => {
49105
49230
  MODEL_PROVIDER_CREDENTIAL_ENV_VARS = [
@@ -49157,10 +49282,10 @@ var init_child_environment = __esm(() => {
49157
49282
  const env = { ...input };
49158
49283
  if (process.platform === "win32")
49159
49284
  return env;
49160
- const home = os5.homedir();
49285
+ const home = os6.homedir();
49161
49286
  const required3 = [
49162
- path9.join(home, ".local/bin"),
49163
- path9.join(home, ".local/share/kifaru/bin"),
49287
+ path10.join(home, ".local/bin"),
49288
+ path10.join(home, ".local/share/kifaru/bin"),
49164
49289
  "/usr/local/sbin",
49165
49290
  "/usr/local/bin",
49166
49291
  "/usr/sbin",
@@ -49168,8 +49293,8 @@ var init_child_environment = __esm(() => {
49168
49293
  "/sbin",
49169
49294
  "/bin"
49170
49295
  ];
49171
- const current = (env.PATH ?? "").split(path9.delimiter).filter(Boolean);
49172
- env.PATH = [...new Set([...current, ...required3])].join(path9.delimiter);
49296
+ const current = (env.PATH ?? "").split(path10.delimiter).filter(Boolean);
49297
+ env.PATH = [...new Set([...current, ...required3])].join(path10.delimiter);
49173
49298
  return env;
49174
49299
  }
49175
49300
  ChildEnvironment.withExecutablePath = withExecutablePath;
@@ -50037,23 +50162,23 @@ var init_main = __esm(() => {
50037
50162
  });
50038
50163
 
50039
50164
  // ../execution-runtime/src/config.ts
50040
- import fs8 from "fs/promises";
50041
- import os6 from "os";
50042
- import path10 from "path";
50165
+ import fs9 from "fs/promises";
50166
+ import os7 from "os";
50167
+ import path11 from "path";
50043
50168
  async function loadRuntimeOptions(cwd, env = process.env) {
50044
- const configDir = process.platform === "win32" ? path10.join(env.APPDATA || path10.join(os6.homedir(), "AppData", "Roaming"), "kifaru", "config") : path10.join(env.XDG_CONFIG_HOME || path10.join(os6.homedir(), ".config"), "kifaru");
50169
+ const configDir = process.platform === "win32" ? path11.join(env.APPDATA || path11.join(os7.homedir(), "AppData", "Roaming"), "kifaru", "config") : path11.join(env.XDG_CONFIG_HOME || path11.join(os7.homedir(), ".config"), "kifaru");
50045
50170
  const directories = [];
50046
- for (let dir = path10.resolve(cwd);; dir = path10.dirname(dir)) {
50171
+ for (let dir = path11.resolve(cwd);; dir = path11.dirname(dir)) {
50047
50172
  directories.unshift(dir);
50048
- if (path10.dirname(dir) === dir)
50173
+ if (path11.dirname(dir) === dir)
50049
50174
  break;
50050
50175
  }
50051
50176
  const files = [
50052
- ...CONFIG_FILENAMES.map((name21) => path10.join(configDir, name21)),
50053
- ...env.KIFARU_CONFIG ? [path10.resolve(cwd, env.KIFARU_CONFIG)] : [],
50054
- ...directories.flatMap((dir) => CONFIG_FILENAMES.map((name21) => path10.join(dir, name21))),
50055
- ...directories.flatMap((dir) => CONFIG_FILENAMES.map((name21) => path10.join(dir, ".kifaru", name21))),
50056
- ...env.KIFARU_CONFIG_DIR ? CONFIG_FILENAMES.map((name21) => path10.join(env.KIFARU_CONFIG_DIR, name21)) : []
50177
+ ...CONFIG_FILENAMES.map((name21) => path11.join(configDir, name21)),
50178
+ ...env.KIFARU_CONFIG ? [path11.resolve(cwd, env.KIFARU_CONFIG)] : [],
50179
+ ...directories.flatMap((dir) => CONFIG_FILENAMES.map((name21) => path11.join(dir, name21))),
50180
+ ...directories.flatMap((dir) => CONFIG_FILENAMES.map((name21) => path11.join(dir, ".kifaru", name21))),
50181
+ ...env.KIFARU_CONFIG_DIR ? CONFIG_FILENAMES.map((name21) => path11.join(env.KIFARU_CONFIG_DIR, name21)) : []
50057
50182
  ];
50058
50183
  const python = {};
50059
50184
  const protectedNames = new Set;
@@ -50086,14 +50211,14 @@ async function loadRuntimeOptions(cwd, env = process.env) {
50086
50211
  }
50087
50212
  };
50088
50213
  for (const file3 of new Set(files)) {
50089
- const text2 = await fs8.readFile(file3, "utf8").catch((error92) => {
50214
+ const text2 = await fs9.readFile(file3, "utf8").catch((error92) => {
50090
50215
  if (error92.code === "ENOENT")
50091
50216
  return;
50092
50217
  throw error92;
50093
50218
  });
50094
50219
  if (text2 !== undefined)
50095
50220
  merge3(text2, file3);
50096
- else if (env.KIFARU_CONFIG && file3 === path10.resolve(cwd, env.KIFARU_CONFIG)) {
50221
+ else if (env.KIFARU_CONFIG && file3 === path11.resolve(cwd, env.KIFARU_CONFIG)) {
50097
50222
  throw new Error(`Kifaru runtime configuration not found: ${file3}`);
50098
50223
  }
50099
50224
  }
@@ -50109,7 +50234,7 @@ var init_config = __esm(() => {
50109
50234
  });
50110
50235
 
50111
50236
  // ../execution-runtime/src/inspect.ts
50112
- import path11 from "path";
50237
+ import path12 from "path";
50113
50238
  async function inspectExecutionRuntime(cwd, env = process.env, options) {
50114
50239
  const runtime = options ?? await loadRuntimeOptions(cwd, env);
50115
50240
  const environment = await prepareHostEnvironment(env, cwd, false, runtime);
@@ -50124,7 +50249,7 @@ async function inspectExecutionRuntime(cwd, env = process.env, options) {
50124
50249
  managedVenvPath: environment.selection.managedVenvPath,
50125
50250
  discovered,
50126
50251
  missing: expected.filter((command) => !discovered.includes(command)),
50127
- helperAvailable: await Bun.file(path11.join(helperDir, "hunt.py")).exists(),
50252
+ helperAvailable: await Bun.file(path12.join(helperDir, "hunt.py")).exists(),
50128
50253
  helperDir
50129
50254
  };
50130
50255
  }
@@ -50183,18 +50308,18 @@ var init_agent_selector = __esm(() => {
50183
50308
  });
50184
50309
 
50185
50310
  // src/invoker-resolver.ts
50186
- import fs9 from "fs";
50187
- import os7 from "os";
50188
- import path12 from "path";
50311
+ import fs10 from "fs";
50312
+ import os8 from "os";
50313
+ import path13 from "path";
50189
50314
  function sessionGatewayFile() {
50190
50315
  if (process.env.KIFARU_SESSION_FILE)
50191
50316
  return process.env.KIFARU_SESSION_FILE;
50192
- const xdg = process.env.XDG_DATA_HOME || path12.join(os7.homedir(), ".local", "share");
50193
- return path12.join(xdg, "kifaru", "data", "auth", "session.json");
50317
+ const xdg = process.env.XDG_DATA_HOME || path13.join(os8.homedir(), ".local", "share");
50318
+ return path13.join(xdg, "kifaru", "data", "auth", "session.json");
50194
50319
  }
50195
50320
  function loadStoredSession() {
50196
50321
  try {
50197
- const raw = fs9.readFileSync(sessionGatewayFile(), "utf8");
50322
+ const raw = fs10.readFileSync(sessionGatewayFile(), "utf8");
50198
50323
  const data = JSON.parse(raw);
50199
50324
  if (!data?.accessToken || !data?.gatewayEnv?.api)
50200
50325
  return null;
@@ -50312,27 +50437,27 @@ var init_pi_python_runtime = __esm(() => {
50312
50437
  });
50313
50438
 
50314
50439
  // src/tui-logger.ts
50315
- import fs10 from "fs";
50316
- import os8 from "os";
50317
- import path13 from "path";
50440
+ import fs11 from "fs";
50441
+ import os9 from "os";
50442
+ import path14 from "path";
50318
50443
  function kifaruDataDir() {
50319
50444
  if (process.env.KIFARU_XDG_DATA_HOME)
50320
50445
  return process.env.KIFARU_XDG_DATA_HOME;
50321
- if (os8.platform() === "win32") {
50322
- return path13.join(process.env.LOCALAPPDATA || path13.join(os8.homedir(), "AppData", "Local"), "kifaru", "data");
50446
+ if (os9.platform() === "win32") {
50447
+ return path14.join(process.env.LOCALAPPDATA || path14.join(os9.homedir(), "AppData", "Local"), "kifaru", "data");
50323
50448
  }
50324
- return path13.join(process.env.XDG_DATA_HOME || path13.join(os8.homedir(), ".local", "share"), "kifaru");
50449
+ return path14.join(process.env.XDG_DATA_HOME || path14.join(os9.homedir(), ".local", "share"), "kifaru");
50325
50450
  }
50326
50451
  function resolveLogFilePath() {
50327
50452
  if (process.env.KIFARU_LOG_FILE)
50328
- return path13.resolve(process.env.KIFARU_LOG_FILE);
50329
- return path13.join(kifaruDataDir(), "log", "dev.log");
50453
+ return path14.resolve(process.env.KIFARU_LOG_FILE);
50454
+ return path14.join(kifaruDataDir(), "log", "dev.log");
50330
50455
  }
50331
50456
  function ensureLogDir() {
50332
50457
  if (!initialized) {
50333
50458
  activeLogPath = resolveLogFilePath();
50334
50459
  try {
50335
- fs10.mkdirSync(path13.dirname(activeLogPath), { recursive: true });
50460
+ fs11.mkdirSync(path14.dirname(activeLogPath), { recursive: true });
50336
50461
  } catch {}
50337
50462
  initialized = true;
50338
50463
  }
@@ -50345,7 +50470,7 @@ function writeLog(level, category, message, extra) {
50345
50470
  const extraStr = extra !== undefined ? ` ${typeof extra === "object" ? JSON.stringify(extra) : String(extra)}` : "";
50346
50471
  const line = `${ts} [${level}] [${category}] ${message}${extraStr}
50347
50472
  `;
50348
- fs10.appendFileSync(file3, line, "utf8");
50473
+ fs11.appendFileSync(file3, line, "utf8");
50349
50474
  } catch {}
50350
50475
  }
50351
50476
  var initialized = false, activeLogPath = "", tuiLog;
@@ -50370,22 +50495,22 @@ var init_tui_logger = __esm(() => {
50370
50495
  });
50371
50496
 
50372
50497
  // src/pi-platform-client.ts
50373
- import fs11 from "fs";
50374
- import path14 from "path";
50498
+ import fs12 from "fs";
50499
+ import path15 from "path";
50375
50500
  function trimSlash(value) {
50376
50501
  return value.replace(/\/+$/, "");
50377
50502
  }
50378
50503
  function findLocalPlatformToken(searchPaths) {
50379
- const repoRoot = path14.resolve(import.meta.dir, "../../..");
50504
+ const repoRoot = path15.resolve(import.meta.dir, "../../..");
50380
50505
  const candidates = searchPaths ?? [
50381
- path14.resolve(process.cwd(), "data/.platform-internal-token"),
50382
- path14.resolve(repoRoot, "data/.platform-internal-token"),
50383
- path14.join(process.env.HOME || "", ".local/share/kifaru/.platform-internal-token")
50506
+ path15.resolve(process.cwd(), "data/.platform-internal-token"),
50507
+ path15.resolve(repoRoot, "data/.platform-internal-token"),
50508
+ path15.join(process.env.HOME || "", ".local/share/kifaru/.platform-internal-token")
50384
50509
  ];
50385
50510
  for (const candidate of candidates) {
50386
50511
  try {
50387
- if (fs11.existsSync(candidate)) {
50388
- const token = fs11.readFileSync(candidate, "utf8").trim();
50512
+ if (fs12.existsSync(candidate)) {
50513
+ const token = fs12.readFileSync(candidate, "utf8").trim();
50389
50514
  if (token.length >= 32)
50390
50515
  return token;
50391
50516
  }
@@ -50423,8 +50548,8 @@ function createPiPlatformClient(options = {}) {
50423
50548
  return disabledClient;
50424
50549
  }
50425
50550
  tuiLog.info("platform", `Platform ingestion enabled -> ${config3.baseURL}`);
50426
- async function request(path15, method, body) {
50427
- const url3 = `${config3.baseURL}/api/v1/${path15}`;
50551
+ async function request(path16, method, body) {
50552
+ const url3 = `${config3.baseURL}/api/v1/${path16}`;
50428
50553
  tuiLog.debug("platform:http", `-> ${method} ${url3}`);
50429
50554
  const response = await fetchImpl(url3, {
50430
50555
  method,
@@ -50492,7 +50617,9 @@ function createPiPlatformClient(options = {}) {
50492
50617
  fingerprint: f.fingerprint || `${f.file}:${f.title}`.slice(0, 512),
50493
50618
  ruleID: f.ruleID || "finding"
50494
50619
  }));
50495
- const response = await request(`runs/${encodeURIComponent(runID)}/findings`, "POST", { findings: normalizedFindings });
50620
+ const response = await request(`runs/${encodeURIComponent(runID)}/findings`, "POST", {
50621
+ findings: normalizedFindings
50622
+ });
50496
50623
  const parsed = await response.json();
50497
50624
  const created = parsed.result?.created ?? 0;
50498
50625
  const updated = parsed.result?.updated ?? 0;
@@ -57063,7 +57190,7 @@ var init_pi_report_finding_tool = __esm(() => {
57063
57190
 
57064
57191
  // src/pi-dossier-sync.ts
57065
57192
  import { readFile } from "fs/promises";
57066
- import path15 from "path";
57193
+ import path16 from "path";
57067
57194
  function targetDossierName(target2) {
57068
57195
  try {
57069
57196
  return new URL(target2.includes("://") ? target2 : `https://${target2}`).hostname.toLowerCase();
@@ -57116,7 +57243,7 @@ async function syncPiDossier(client, context2, cwd, read = readFile) {
57116
57243
  return { ...NOTHING, skipped: "unparseable-target" };
57117
57244
  let raw;
57118
57245
  try {
57119
- raw = await read(path15.join(cwd, ".kifaru", "dossiers", `${name21}.json`), "utf8");
57246
+ raw = await read(path16.join(cwd, ".kifaru", "dossiers", `${name21}.json`), "utf8");
57120
57247
  } catch (error92) {
57121
57248
  if (error92.code === "ENOENT")
57122
57249
  return { ...NOTHING, skipped: "no-dossier-file" };
@@ -57352,9 +57479,11 @@ ${runtimePrompt(state, cwd)}`
57352
57479
  };
57353
57480
  }
57354
57481
  async function runKifaruPiSdkTui(options = {}) {
57482
+ process.env.PI_SKIP_VERSION_CHECK ||= "1";
57355
57483
  const cwd = options.cwd ?? process.cwd();
57356
57484
  const agentDir = getAgentDir2();
57357
57485
  const kifaruSkillsPath = materializeKifaruSkills();
57486
+ const kifaruThemesPath = materializeKifaruThemes();
57358
57487
  const catalog = options.catalog ?? new ModelCatalogRegistry;
57359
57488
  const initial = splitThinkingRef(options.initialModelRef ?? "azure/FW-DeepSeek-V4-Flash-0731");
57360
57489
  const initialResolution = catalog.resolve(initial.modelRef);
@@ -57409,7 +57538,8 @@ async function runKifaruPiSdkTui(options = {}) {
57409
57538
  shellPath: settingsManager.getShellPath()
57410
57539
  })
57411
57540
  ],
57412
- ...kifaruSkillsPath ? { additionalSkillPaths: [kifaruSkillsPath] } : {}
57541
+ ...kifaruSkillsPath ? { additionalSkillPaths: [kifaruSkillsPath] } : {},
57542
+ ...kifaruThemesPath ? { additionalThemePaths: [kifaruThemesPath] } : {}
57413
57543
  }
57414
57544
  });
57415
57545
  const hasExistingMessages = sessionManager.buildSessionContext().messages.length > 0;
@@ -57439,7 +57569,8 @@ async function runKifaruPiSdkTui(options = {}) {
57439
57569
  startupDiagnostics: [...runtime.diagnostics],
57440
57570
  modelFallbackMessage: runtime.modelFallbackMessage,
57441
57571
  initialImages: [],
57442
- initialMessages: []
57572
+ initialMessages: [],
57573
+ ...kifaruThemesPath && !runtime.session.settingsManager.getThemeSetting() ? { initialThemeSetting: KIFARU_THEME_NAME } : {}
57443
57574
  });
57444
57575
  await mode.run();
57445
57576
  }
@@ -57835,8 +57966,8 @@ function forwardSignals(child) {
57835
57966
  }
57836
57967
 
57837
57968
  // src/headless-command.ts
57838
- import fs5 from "fs";
57839
- import path5 from "path";
57969
+ import fs6 from "fs";
57970
+ import path6 from "path";
57840
57971
  import { parseArgs } from "util";
57841
57972
  var HEADLESS_HELP = `Kifaru headless \u2014 run a local Pi stage and compile a report.
57842
57973
 
@@ -57932,8 +58063,8 @@ function parseHeadlessArgs(args) {
57932
58063
  runId,
57933
58064
  stageInput,
57934
58065
  model: values.model,
57935
- dbPath: path5.resolve(values.db),
57936
- outDir: path5.resolve(values.out)
58066
+ dbPath: path6.resolve(values.db),
58067
+ outDir: path6.resolve(values.out)
57937
58068
  };
57938
58069
  }
57939
58070
  async function runHeadlessCommand(args) {
@@ -57958,9 +58089,9 @@ async function runHeadlessCommand(args) {
57958
58089
  workflowKey: options.stageInput.workflowKey,
57959
58090
  fallbackTarget: options.stageInput.target.url
57960
58091
  });
57961
- fs5.mkdirSync(options.outDir, { recursive: true });
57962
- const reportPath = path5.join(options.outDir, `${options.runId}.json`);
57963
- fs5.writeFileSync(reportPath, JSON.stringify(record3, null, 2));
58092
+ fs6.mkdirSync(options.outDir, { recursive: true });
58093
+ const reportPath = path6.join(options.outDir, `${options.runId}.json`);
58094
+ fs6.writeFileSync(reportPath, JSON.stringify(record3, null, 2));
57964
58095
  console.log(`Status: ${outcome2.status}
57965
58096
  Report: ${reportPath}`);
57966
58097
  return outcome2.status === "failed" || outcome2.status === "blocked" ? 1 : 0;
@@ -58082,7 +58213,7 @@ Ctrl+C stops the gateway.`);
58082
58213
  async function handleCli() {
58083
58214
  const args = process.argv.slice(2);
58084
58215
  if (args.includes("--version") || args.includes("-v")) {
58085
- console.log("1.0.180");
58216
+ console.log("1.0.181");
58086
58217
  process.exit(0);
58087
58218
  }
58088
58219
  if (args[0] === "dashboard") {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kifaru",
3
- "version": "1.0.180",
4
- "gitHead": "be4ccf8ddffc4618219792b9f9f7beb8136f9275",
3
+ "version": "1.0.181",
4
+ "gitHead": "871ffee5997dbc473d33cdc4039cd4cfa34dfc89",
5
5
  "description": "Kifaru security agent on the Pi runtime",
6
6
  "type": "module",
7
7
  "license": "MIT",
@@ -19,6 +19,9 @@
19
19
  ],
20
20
  "skills": [
21
21
  "./skills"
22
+ ],
23
+ "themes": [
24
+ "./themes"
22
25
  ]
23
26
  },
24
27
  "files": [
@@ -28,6 +31,7 @@
28
31
  "LICENSE",
29
32
  "skills",
30
33
  "extensions",
34
+ "themes",
31
35
  "dashboard"
32
36
  ],
33
37
  "dependencies": {
@@ -0,0 +1,90 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
+ "name": "kifaru-dark",
4
+ "vars": {
5
+ "accent": "#5a90c2",
6
+ "accentInk": "#82abd6",
7
+ "ink2": "#a7aeb8",
8
+ "muted": "#6e767f",
9
+ "hair": "#222831",
10
+ "border": "#293039",
11
+ "raised": "#1a2027",
12
+ "surface2": "#1c222a",
13
+ "accentSoft": "#18232f",
14
+ "s6": "#305d84",
15
+ "s5": "#4574a3",
16
+ "crit": "#cf5a55",
17
+ "high": "#c58a48",
18
+ "med": "#bda23c",
19
+ "good": "#4aa66a",
20
+ "low": "#5b93cb",
21
+ "info": "#8b929b",
22
+ "critBg": "#33201f",
23
+ "highBg": "#312a1c",
24
+ "medBg": "#2e2915",
25
+ "lowBg": "#16222f",
26
+ "infoBg": "#22262b",
27
+ "goodBg": "#152a1d"
28
+ },
29
+ "colors": {
30
+ "accent": "accent",
31
+ "border": "border",
32
+ "borderAccent": "accentInk",
33
+ "borderMuted": "hair",
34
+ "success": "good",
35
+ "error": "crit",
36
+ "warning": "high",
37
+ "muted": "ink2",
38
+ "dim": "muted",
39
+ "text": "",
40
+ "thinkingText": "ink2",
41
+ "selectedBg": "surface2",
42
+ "scrollbarTrack": "hair",
43
+ "scrollbarThumb": "muted",
44
+ "userMessageBg": "raised",
45
+ "userMessageText": "",
46
+ "customMessageBg": "accentSoft",
47
+ "customMessageText": "",
48
+ "customMessageLabel": "accent",
49
+ "toolPendingBg": "infoBg",
50
+ "toolSuccessBg": "goodBg",
51
+ "toolErrorBg": "critBg",
52
+ "toolTitle": "accentInk",
53
+ "toolOutput": "",
54
+ "mdHeading": "accentInk",
55
+ "mdLink": "accent",
56
+ "mdLinkUrl": "muted",
57
+ "mdCode": "low",
58
+ "mdCodeBlock": "",
59
+ "mdCodeBlockBorder": "border",
60
+ "mdQuote": "ink2",
61
+ "mdQuoteBorder": "border",
62
+ "mdHr": "hair",
63
+ "mdListBullet": "low",
64
+ "toolDiffAdded": "good",
65
+ "toolDiffRemoved": "crit",
66
+ "toolDiffContext": "muted",
67
+ "syntaxComment": "muted",
68
+ "syntaxKeyword": "accent",
69
+ "syntaxFunction": "accentInk",
70
+ "syntaxVariable": "high",
71
+ "syntaxString": "good",
72
+ "syntaxNumber": "med",
73
+ "syntaxType": "low",
74
+ "syntaxOperator": "accent",
75
+ "syntaxPunctuation": "ink2",
76
+ "thinkingOff": "muted",
77
+ "thinkingMinimal": "s6",
78
+ "thinkingLow": "s5",
79
+ "thinkingMedium": "accent",
80
+ "thinkingHigh": "accentInk",
81
+ "thinkingXhigh": "high",
82
+ "thinkingMax": "crit",
83
+ "bashMode": "med"
84
+ },
85
+ "export": {
86
+ "pageBg": "#0d1013",
87
+ "cardBg": "#151a1f",
88
+ "infoBg": "#1c222a"
89
+ }
90
+ }