hanoman 0.1.54 → 0.1.55
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.json
CHANGED
package/dist/server.js
CHANGED
|
@@ -39259,6 +39259,33 @@ function installCommand(m, agent, shell = shellBin()) {
|
|
|
39259
39259
|
return [shell, "-lc", `${m.install[agent].join(" && ")}; exec '${shell}' -l`];
|
|
39260
39260
|
}
|
|
39261
39261
|
|
|
39262
|
+
// src/services/terminal-diag.ts
|
|
39263
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8, statSync as statSync3, rmSync as rmSync4 } from "node:fs";
|
|
39264
|
+
import { join as join15 } from "node:path";
|
|
39265
|
+
var DIAG_MAX_BYTES = 2 * 1024 * 1024;
|
|
39266
|
+
var KINDS = /* @__PURE__ */ new Set(["key", "comp", "data", "ack", "pred"]);
|
|
39267
|
+
var ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
39268
|
+
function diagFile(home3, sessionId2) {
|
|
39269
|
+
if (!ID.test(sessionId2)) throw new Error(`id sesi tak sah untuk diag: ${sessionId2}`);
|
|
39270
|
+
return join15(home3, "diag", `${sessionId2}.jsonl`);
|
|
39271
|
+
}
|
|
39272
|
+
function usable(ev) {
|
|
39273
|
+
if (!ev || typeof ev !== "object") return false;
|
|
39274
|
+
const e = ev;
|
|
39275
|
+
return typeof e.t === "number" && typeof e.k === "string" && KINDS.has(e.k) && typeof e.v === "string" && (e.n === void 0 || typeof e.n === "number");
|
|
39276
|
+
}
|
|
39277
|
+
function appendDiag(home3, sessionId2, events2) {
|
|
39278
|
+
const file = diagFile(home3, sessionId2);
|
|
39279
|
+
const rows = events2.filter(usable);
|
|
39280
|
+
if (!rows.length) return;
|
|
39281
|
+
mkdirSync8(join15(home3, "diag"), { recursive: true });
|
|
39282
|
+
try {
|
|
39283
|
+
if (statSync3(file).size > DIAG_MAX_BYTES) rmSync4(file);
|
|
39284
|
+
} catch {
|
|
39285
|
+
}
|
|
39286
|
+
appendFileSync2(file, rows.map((r) => JSON.stringify(r)).join("\n") + "\n");
|
|
39287
|
+
}
|
|
39288
|
+
|
|
39262
39289
|
// src/routes/terminal.ts
|
|
39263
39290
|
init_notifications();
|
|
39264
39291
|
init_stage_machine();
|
|
@@ -39608,6 +39635,12 @@ async function terminal_default(app2, opts) {
|
|
|
39608
39635
|
writeTo(id, m.d, client);
|
|
39609
39636
|
if (typeof m.seq === "number") socket2.send(JSON.stringify({ t: "ack", seq: m.seq }));
|
|
39610
39637
|
} else if (m.t === "resize" && m.cols && m.rows) resize(id, m.cols, m.rows);
|
|
39638
|
+
else if (m.t === "diag" && Array.isArray(m.ev)) {
|
|
39639
|
+
try {
|
|
39640
|
+
appendDiag(resolveHome(), id, m.ev);
|
|
39641
|
+
} catch {
|
|
39642
|
+
}
|
|
39643
|
+
}
|
|
39611
39644
|
});
|
|
39612
39645
|
const revalidate = setInterval(() => {
|
|
39613
39646
|
void revalidateWsPrincipal(req, principal).then((ok2) => {
|
|
@@ -39801,9 +39834,9 @@ import { readFileSync as readFileSync8 } from "node:fs";
|
|
|
39801
39834
|
// src/services/vps-ssh.ts
|
|
39802
39835
|
init_config2();
|
|
39803
39836
|
import { spawn as spawn4 } from "node:child_process";
|
|
39804
|
-
import { mkdtempSync, rmSync as
|
|
39837
|
+
import { mkdtempSync, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
39805
39838
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
39806
|
-
import { dirname as dirname10, join as
|
|
39839
|
+
import { dirname as dirname10, join as join16 } from "node:path";
|
|
39807
39840
|
var sshBin = () => effectiveStr("HANOMAN_SSH_BIN") ?? "ssh";
|
|
39808
39841
|
function consoleArgv(t) {
|
|
39809
39842
|
return [
|
|
@@ -39818,8 +39851,8 @@ function consoleArgv(t) {
|
|
|
39818
39851
|
];
|
|
39819
39852
|
}
|
|
39820
39853
|
function askpassScript() {
|
|
39821
|
-
const dir2 = mkdtempSync(
|
|
39822
|
-
const path2 =
|
|
39854
|
+
const dir2 = mkdtempSync(join16(tmpdir3(), "hanoman-askpass-"));
|
|
39855
|
+
const path2 = join16(dir2, "askpass.sh");
|
|
39823
39856
|
writeFileSync4(path2, `#!/bin/sh
|
|
39824
39857
|
printf '%s' "$HANOMAN_SSH_PASSWORD"
|
|
39825
39858
|
`, { mode: 448 });
|
|
@@ -39859,7 +39892,7 @@ function sshExec(t, remoteCmd, opts = {}) {
|
|
|
39859
39892
|
const timer9 = setTimeout(() => p.kill("SIGKILL"), opts.timeoutMs ?? 6e4);
|
|
39860
39893
|
const done = (r) => {
|
|
39861
39894
|
clearTimeout(timer9);
|
|
39862
|
-
if (askpass)
|
|
39895
|
+
if (askpass) rmSync5(dirname10(askpass), { recursive: true, force: true });
|
|
39863
39896
|
resolve21(r);
|
|
39864
39897
|
};
|
|
39865
39898
|
p.stdout.on("data", (d) => {
|
|
@@ -39880,15 +39913,15 @@ function sshExec(t, remoteCmd, opts = {}) {
|
|
|
39880
39913
|
// src/services/vps-audit.ts
|
|
39881
39914
|
init_db();
|
|
39882
39915
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
39883
|
-
import { join as
|
|
39916
|
+
import { join as join18 } from "node:path";
|
|
39884
39917
|
|
|
39885
39918
|
// src/runner/deps.ts
|
|
39886
39919
|
import { existsSync as existsSync11 } from "node:fs";
|
|
39887
|
-
import { dirname as dirname11, join as
|
|
39920
|
+
import { dirname as dirname11, join as join17 } from "node:path";
|
|
39888
39921
|
function repoRootFrom(startDir) {
|
|
39889
39922
|
let dir2 = startDir;
|
|
39890
39923
|
for (let i = 0; i < 8; i++) {
|
|
39891
|
-
if (existsSync11(
|
|
39924
|
+
if (existsSync11(join17(dir2, "pnpm-workspace.yaml"))) return dir2;
|
|
39892
39925
|
const parent = dirname11(dir2);
|
|
39893
39926
|
if (parent === dir2) break;
|
|
39894
39927
|
dir2 = parent;
|
|
@@ -39994,7 +40027,7 @@ function parseHealth(out4) {
|
|
|
39994
40027
|
return { uptime: h.uptime ?? "", disk: h.disk ?? "", mem: h.mem ?? "", load: h.load ?? "" };
|
|
39995
40028
|
}
|
|
39996
40029
|
var target = (v) => ({ host: v.host, port: v.port, user: v.user, keyPath: v.keyPath });
|
|
39997
|
-
var scriptPath = (f) =>
|
|
40030
|
+
var scriptPath = (f) => join18(repoRoot(), "server", "scripts", "vps", f);
|
|
39998
40031
|
async function itemStatesOf(vpsId) {
|
|
39999
40032
|
const rows = await prisma.vpsItemState.findMany({ where: { vpsId } });
|
|
40000
40033
|
return Object.fromEntries(rows.map((s2) => [s2.itemId, { na: s2.na, attested: s2.attested }]));
|
|
@@ -40142,31 +40175,31 @@ async function buildChecklist(vpsId) {
|
|
|
40142
40175
|
init_src2();
|
|
40143
40176
|
init_config2();
|
|
40144
40177
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
40145
|
-
import { chmodSync as chmodSync3, copyFileSync, existsSync as existsSync12, mkdirSync as
|
|
40178
|
+
import { chmodSync as chmodSync3, copyFileSync, existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync9, unlinkSync as unlinkSync2 } from "node:fs";
|
|
40146
40179
|
import { homedir as homedir5 } from "node:os";
|
|
40147
|
-
import { join as
|
|
40180
|
+
import { join as join19 } from "node:path";
|
|
40148
40181
|
var keyDir = () => effectiveStr("HANOMAN_SSH_KEY_DIR") ?? resolveDataDirs().sshKeys;
|
|
40149
40182
|
var KEY_FILES = ["id_ed25519", "id_ed25519.pub"];
|
|
40150
40183
|
function adoptLegacyKey(dir2) {
|
|
40151
40184
|
if (effectiveStr("HANOMAN_SSH_KEY_DIR")) return;
|
|
40152
|
-
const legacy =
|
|
40185
|
+
const legacy = join19(homedir5(), ".hanoman");
|
|
40153
40186
|
if (legacy === dir2) return;
|
|
40154
|
-
if (!KEY_FILES.every((f) => existsSync12(
|
|
40155
|
-
|
|
40187
|
+
if (!KEY_FILES.every((f) => existsSync12(join19(legacy, f)))) return;
|
|
40188
|
+
mkdirSync9(dir2, { recursive: true, mode: 448 });
|
|
40156
40189
|
for (const f of KEY_FILES) {
|
|
40157
|
-
copyFileSync(
|
|
40158
|
-
chmodSync3(
|
|
40190
|
+
copyFileSync(join19(legacy, f), join19(dir2, f));
|
|
40191
|
+
chmodSync3(join19(dir2, f), 384);
|
|
40159
40192
|
}
|
|
40160
|
-
for (const f of KEY_FILES) unlinkSync2(
|
|
40193
|
+
for (const f of KEY_FILES) unlinkSync2(join19(legacy, f));
|
|
40161
40194
|
console.log(`vps: key SSH dipindah dari ${legacy} ke ${dir2} (SPEC-846 \u2014 satu batas backup)`);
|
|
40162
40195
|
}
|
|
40163
40196
|
function ensureHanomanKey() {
|
|
40164
40197
|
const dir2 = keyDir();
|
|
40165
|
-
const privPath =
|
|
40198
|
+
const privPath = join19(dir2, KEY_FILES[0]);
|
|
40166
40199
|
const pubPath = `${privPath}.pub`;
|
|
40167
40200
|
if (!existsSync12(privPath)) adoptLegacyKey(dir2);
|
|
40168
40201
|
if (!existsSync12(privPath)) {
|
|
40169
|
-
|
|
40202
|
+
mkdirSync9(dir2, { recursive: true, mode: 448 });
|
|
40170
40203
|
execFileSync2(
|
|
40171
40204
|
"ssh-keygen",
|
|
40172
40205
|
["-t", "ed25519", "-N", "", "-C", "hanoman", "-f", privPath],
|
|
@@ -40401,7 +40434,7 @@ init_config2();
|
|
|
40401
40434
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
40402
40435
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
40403
40436
|
import { homedir as homedir7 } from "node:os";
|
|
40404
|
-
import { join as
|
|
40437
|
+
import { join as join20 } from "node:path";
|
|
40405
40438
|
var USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
|
|
40406
40439
|
var TTL_MS2 = 3e4;
|
|
40407
40440
|
var lastOk = null;
|
|
@@ -40414,7 +40447,7 @@ var LABELS = {
|
|
|
40414
40447
|
var humanize = (k) => k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
40415
40448
|
var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
40416
40449
|
function credsFile() {
|
|
40417
|
-
return
|
|
40450
|
+
return join20(effectiveStr("CLAUDE_CONFIG_DIR") ?? join20(homedir7(), ".claude"), ".credentials.json");
|
|
40418
40451
|
}
|
|
40419
40452
|
function readAccessToken() {
|
|
40420
40453
|
if (process.platform === "darwin" && !effectiveStr("CLAUDE_CONFIG_DIR")) {
|
|
@@ -40488,14 +40521,14 @@ async function getLimits() {
|
|
|
40488
40521
|
// src/services/codex-limits.ts
|
|
40489
40522
|
import { open as open3, readdir as readdir4, stat as stat2 } from "node:fs/promises";
|
|
40490
40523
|
import { homedir as homedir8 } from "node:os";
|
|
40491
|
-
import { join as
|
|
40524
|
+
import { join as join21 } from "node:path";
|
|
40492
40525
|
var TTL_MS3 = 3e4;
|
|
40493
40526
|
var STALE_AFTER_MS = 12 * 36e5;
|
|
40494
40527
|
var TAIL_BYTES = 512 * 1024;
|
|
40495
40528
|
var MAX_FILES = 8;
|
|
40496
40529
|
var cache3 = null;
|
|
40497
40530
|
var freshUntil2 = 0;
|
|
40498
|
-
var codexSessionsDir = () =>
|
|
40531
|
+
var codexSessionsDir = () => join21(process.env.CODEX_HOME ?? join21(homedir8(), ".codex"), "sessions");
|
|
40499
40532
|
var UNAVAILABLE = { status: "unavailable", windows: [], fetchedAt: null, plan: null };
|
|
40500
40533
|
function windowLabel(minutes) {
|
|
40501
40534
|
if (minutes === 300) return "Sesi 5 jam";
|
|
@@ -40528,7 +40561,7 @@ async function recentRollouts(dir2) {
|
|
|
40528
40561
|
return [];
|
|
40529
40562
|
}
|
|
40530
40563
|
const stamped = await Promise.all(entries.map(async (rel) => {
|
|
40531
|
-
const full =
|
|
40564
|
+
const full = join21(dir2, rel);
|
|
40532
40565
|
try {
|
|
40533
40566
|
return { full, mtime: (await stat2(full)).mtimeMs };
|
|
40534
40567
|
} catch {
|
|
@@ -41199,7 +41232,7 @@ init_config2();
|
|
|
41199
41232
|
init_src2();
|
|
41200
41233
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
41201
41234
|
import { mkdir as mkdir5, writeFile as writeFile4, readFile as readFile4, unlink as unlink4, readdir as readdir5, stat as stat3 } from "node:fs/promises";
|
|
41202
|
-
import { join as
|
|
41235
|
+
import { join as join22, resolve as resolve19, basename as basename6 } from "node:path";
|
|
41203
41236
|
var MAX_TRANSCRIPT_BYTES = 1024 * 1024;
|
|
41204
41237
|
function transcriptDir() {
|
|
41205
41238
|
return resolve19(effectiveStr("HANOMAN_TRANSCRIPT_DIR")?.trim() || resolveDataDirs().transcripts);
|
|
@@ -41220,13 +41253,13 @@ async function saveTranscript(text) {
|
|
|
41220
41253
|
const dir2 = transcriptDir();
|
|
41221
41254
|
await mkdir5(dir2, { recursive: true, mode: 448 });
|
|
41222
41255
|
const key = `${randomUUID7()}.log`;
|
|
41223
|
-
await writeFile4(
|
|
41256
|
+
await writeFile4(join22(dir2, key), body, { encoding: "utf8", mode: 384 });
|
|
41224
41257
|
return { key, bytes: Buffer.byteLength(body, "utf8"), truncated };
|
|
41225
41258
|
}
|
|
41226
41259
|
async function readTranscript(key) {
|
|
41227
41260
|
if (!key) return null;
|
|
41228
41261
|
try {
|
|
41229
|
-
return await readFile4(
|
|
41262
|
+
return await readFile4(join22(transcriptDir(), basename6(key)), "utf8");
|
|
41230
41263
|
} catch {
|
|
41231
41264
|
return null;
|
|
41232
41265
|
}
|
|
@@ -41234,7 +41267,7 @@ async function readTranscript(key) {
|
|
|
41234
41267
|
async function deleteTranscript(key) {
|
|
41235
41268
|
if (!key) return;
|
|
41236
41269
|
try {
|
|
41237
|
-
await unlink4(
|
|
41270
|
+
await unlink4(join22(transcriptDir(), basename6(key)));
|
|
41238
41271
|
} catch (e) {
|
|
41239
41272
|
if (e.code !== "ENOENT") throw e;
|
|
41240
41273
|
}
|
|
@@ -41252,7 +41285,7 @@ async function listTranscripts() {
|
|
|
41252
41285
|
for (const name2 of names) {
|
|
41253
41286
|
if (!name2.endsWith(".log")) continue;
|
|
41254
41287
|
try {
|
|
41255
|
-
rows.push({ key: name2, mtimeMs: (await stat3(
|
|
41288
|
+
rows.push({ key: name2, mtimeMs: (await stat3(join22(dir2, name2))).mtimeMs });
|
|
41256
41289
|
} catch {
|
|
41257
41290
|
}
|
|
41258
41291
|
}
|
|
@@ -42712,9 +42745,9 @@ init_pty();
|
|
|
42712
42745
|
init_session_sandbox();
|
|
42713
42746
|
import { execFile as execFile12 } from "node:child_process";
|
|
42714
42747
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
42715
|
-
import { mkdirSync as
|
|
42748
|
+
import { mkdirSync as mkdirSync10, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
42716
42749
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
42717
|
-
import { join as
|
|
42750
|
+
import { join as join23 } from "node:path";
|
|
42718
42751
|
var binFor = (agent) => agent === "codex" ? effectiveStr("HANOMAN_CODEX_BIN") ?? "codex" : effectiveStr("HANOMAN_CLAUDE_BIN") ?? "claude";
|
|
42719
42752
|
function leadArgv(o) {
|
|
42720
42753
|
if (o.agent === "codex") {
|
|
@@ -42742,12 +42775,12 @@ function leadProcess(prompt, o, env = process.env) {
|
|
|
42742
42775
|
const mode = env.HANOMAN_SESSION_SANDBOX ?? (env.NODE_ENV === "production" ? "required" : "off");
|
|
42743
42776
|
if (mode === "off") return { file, args: directArgs, cwd: o.cwd, cleanup: () => {
|
|
42744
42777
|
} };
|
|
42745
|
-
const promptDir =
|
|
42746
|
-
|
|
42747
|
-
const promptFile =
|
|
42778
|
+
const promptDir = join23(tmpdir4(), "hanoman-prompts");
|
|
42779
|
+
mkdirSync10(promptDir, { recursive: true, mode: 448 });
|
|
42780
|
+
const promptFile = join23(promptDir, `oneshot-${randomUUID9()}`);
|
|
42748
42781
|
writeFileSync5(promptFile, prompt, { flag: "wx", mode: 384 });
|
|
42749
|
-
const workspace = o.cwd ??
|
|
42750
|
-
if (!o.cwd)
|
|
42782
|
+
const workspace = o.cwd ?? join23(tmpdir4(), `hanoman-oneshot-${randomUUID9()}`);
|
|
42783
|
+
if (!o.cwd) mkdirSync10(workspace, { recursive: false, mode: 448 });
|
|
42751
42784
|
try {
|
|
42752
42785
|
const argsWithoutPrompt = directArgs.slice(0, -1);
|
|
42753
42786
|
const command = [file, ...argsWithoutPrompt].map(shellQuote).join(" ") + ` "$(cat ${shellQuote(promptFile)})"`;
|
|
@@ -42764,13 +42797,13 @@ function leadProcess(prompt, o, env = process.env) {
|
|
|
42764
42797
|
args: sandbox.slice(1),
|
|
42765
42798
|
promptFile,
|
|
42766
42799
|
cleanup: () => {
|
|
42767
|
-
|
|
42768
|
-
if (!o.cwd)
|
|
42800
|
+
rmSync6(promptFile, { force: true });
|
|
42801
|
+
if (!o.cwd) rmSync6(workspace, { recursive: true, force: true });
|
|
42769
42802
|
}
|
|
42770
42803
|
};
|
|
42771
42804
|
} catch (error) {
|
|
42772
|
-
|
|
42773
|
-
if (!o.cwd)
|
|
42805
|
+
rmSync6(promptFile, { force: true });
|
|
42806
|
+
if (!o.cwd) rmSync6(workspace, { recursive: true, force: true });
|
|
42774
42807
|
throw error;
|
|
42775
42808
|
}
|
|
42776
42809
|
}
|
|
@@ -44272,9 +44305,9 @@ var US2 = "";
|
|
|
44272
44305
|
var RS = "";
|
|
44273
44306
|
var NO_REPO = "project ini belum ditautkan ke repo di mesin ini";
|
|
44274
44307
|
var NO_TAG = "repo project ini belum punya tag rilis";
|
|
44275
|
-
var
|
|
44308
|
+
var usable2 = (repoDir) => !!repoDir && existsSync15(repoDir);
|
|
44276
44309
|
async function listTags(repoDir) {
|
|
44277
|
-
if (!
|
|
44310
|
+
if (!usable2(repoDir)) return { tags: [], head: null, reason: NO_REPO };
|
|
44278
44311
|
try {
|
|
44279
44312
|
const { stdout } = await exec10("git", ["tag", "--list", "--sort=-creatordate"], { cwd: repoDir, ...GIT8 });
|
|
44280
44313
|
const tags = stdout.split("\n").map((s2) => s2.trim()).filter(Boolean);
|
|
@@ -44302,7 +44335,7 @@ async function logRange(repoDir, range) {
|
|
|
44302
44335
|
}).filter((x) => x !== null);
|
|
44303
44336
|
}
|
|
44304
44337
|
async function collectCommits(repoDir, fromSha, toSha) {
|
|
44305
|
-
if (!
|
|
44338
|
+
if (!usable2(repoDir)) return { ok: false, reason: NO_REPO };
|
|
44306
44339
|
for (const rev of [fromSha, toSha])
|
|
44307
44340
|
if (!await revExists(repoDir, rev)) return { ok: false, reason: `revisi "${rev}" tak dikenal di repo project` };
|
|
44308
44341
|
try {
|
|
@@ -44317,7 +44350,7 @@ async function collectCommits(repoDir, fromSha, toSha) {
|
|
|
44317
44350
|
async function collectVersions(repoDir, fromTag, toTag) {
|
|
44318
44351
|
const { tags, reason } = await listTags(repoDir);
|
|
44319
44352
|
if (reason) return { ok: false, reason };
|
|
44320
|
-
if (!
|
|
44353
|
+
if (!usable2(repoDir)) return { ok: false, reason: NO_REPO };
|
|
44321
44354
|
if (!tags.includes(toTag)) return { ok: false, reason: `tag "${toTag}" tak ada di repo project` };
|
|
44322
44355
|
if (fromTag && !tags.includes(fromTag)) return { ok: false, reason: `tag "${fromTag}" tak ada di repo project` };
|
|
44323
44356
|
const prev = fromTag ?? await previousTag(repoDir, toTag);
|
|
@@ -44535,7 +44568,7 @@ init_db();
|
|
|
44535
44568
|
init_src();
|
|
44536
44569
|
import { readFileSync as readFileSync13 } from "node:fs";
|
|
44537
44570
|
import { homedir as homedir9 } from "node:os";
|
|
44538
|
-
import { join as
|
|
44571
|
+
import { join as join24 } from "node:path";
|
|
44539
44572
|
var home = () => process.env.HOME || homedir9();
|
|
44540
44573
|
var readJson2 = (path2) => {
|
|
44541
44574
|
try {
|
|
@@ -44552,7 +44585,7 @@ var serversOf = (node) => {
|
|
|
44552
44585
|
var codexServers = () => {
|
|
44553
44586
|
let text;
|
|
44554
44587
|
try {
|
|
44555
|
-
text = readFileSync13(
|
|
44588
|
+
text = readFileSync13(join24(home(), ".codex", "config.toml"), "utf8");
|
|
44556
44589
|
} catch {
|
|
44557
44590
|
return [];
|
|
44558
44591
|
}
|
|
@@ -44565,12 +44598,12 @@ var codexServers = () => {
|
|
|
44565
44598
|
};
|
|
44566
44599
|
function mcpServerNames(repoDir) {
|
|
44567
44600
|
const names = [];
|
|
44568
|
-
const claudeJson = readJson2(
|
|
44601
|
+
const claudeJson = readJson2(join24(home(), ".claude.json"));
|
|
44569
44602
|
names.push(...serversOf(claudeJson));
|
|
44570
44603
|
if (repoDir) {
|
|
44571
44604
|
const projects = claudeJson?.projects;
|
|
44572
44605
|
if (projects && typeof projects === "object") names.push(...serversOf(projects[repoDir]));
|
|
44573
|
-
names.push(...serversOf(readJson2(
|
|
44606
|
+
names.push(...serversOf(readJson2(join24(repoDir, ".mcp.json"))));
|
|
44574
44607
|
}
|
|
44575
44608
|
names.push(...codexServers());
|
|
44576
44609
|
return [...new Set(names.filter(Boolean))].sort((a, b) => a.localeCompare(b));
|
|
@@ -46054,9 +46087,9 @@ ${baru}`;
|
|
|
46054
46087
|
// src/services/portal-chat/workspace.ts
|
|
46055
46088
|
init_src();
|
|
46056
46089
|
init_db();
|
|
46057
|
-
import { mkdirSync as
|
|
46090
|
+
import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync2, rmSync as rmSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
46058
46091
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
46059
|
-
import { join as
|
|
46092
|
+
import { join as join25 } from "node:path";
|
|
46060
46093
|
var STAGE_LABEL = {
|
|
46061
46094
|
brainstorming: "Dirumuskan",
|
|
46062
46095
|
objective: "Dirumuskan",
|
|
@@ -46111,7 +46144,7 @@ ${c.body}
|
|
|
46111
46144
|
${baris.join("\n")}`;
|
|
46112
46145
|
}
|
|
46113
46146
|
async function buildChatWorkspace(projectId) {
|
|
46114
|
-
const dir2 = mkdtempSync2(
|
|
46147
|
+
const dir2 = mkdtempSync2(join25(tmpdir5(), "hanoman-portal-chat-"));
|
|
46115
46148
|
try {
|
|
46116
46149
|
const project = await prisma.project.findUnique({
|
|
46117
46150
|
where: { id: projectId },
|
|
@@ -46132,7 +46165,7 @@ async function buildChatWorkspace(projectId) {
|
|
|
46132
46165
|
});
|
|
46133
46166
|
const files = [];
|
|
46134
46167
|
const tulis = (rel, isi) => {
|
|
46135
|
-
writeFileSync7(
|
|
46168
|
+
writeFileSync7(join25(dir2, rel), isi, { mode: 384 });
|
|
46136
46169
|
files.push(rel);
|
|
46137
46170
|
};
|
|
46138
46171
|
tulis("project.md", renderProjectDoc(project));
|
|
@@ -46141,16 +46174,16 @@ async function buildChatWorkspace(projectId) {
|
|
|
46141
46174
|
tulis("catatan-rilis.md", renderChangelogDoc(changelogs));
|
|
46142
46175
|
const prds = await listPrds(projectId);
|
|
46143
46176
|
if (prds.length) {
|
|
46144
|
-
|
|
46177
|
+
mkdirSync11(join25(dir2, "dokumen"), { mode: 448 });
|
|
46145
46178
|
for (const prd of prds) {
|
|
46146
46179
|
const isi = await readPrd(projectId, prd.path);
|
|
46147
46180
|
if (!isi) continue;
|
|
46148
|
-
tulis(
|
|
46181
|
+
tulis(join25("dokumen", `${prd.slug.replaceAll("/", "-")}.md`), isi);
|
|
46149
46182
|
}
|
|
46150
46183
|
}
|
|
46151
|
-
return { dir: dir2, files, cleanup: () =>
|
|
46184
|
+
return { dir: dir2, files, cleanup: () => rmSync7(dir2, { recursive: true, force: true }) };
|
|
46152
46185
|
} catch (error) {
|
|
46153
|
-
|
|
46186
|
+
rmSync7(dir2, { recursive: true, force: true });
|
|
46154
46187
|
throw error;
|
|
46155
46188
|
}
|
|
46156
46189
|
}
|
|
@@ -46657,13 +46690,13 @@ init_db();
|
|
|
46657
46690
|
// src/services/bootstrap.ts
|
|
46658
46691
|
import { createHash as createHash9, randomBytes as randomBytes10, timingSafeEqual as timingSafeEqual3 } from "node:crypto";
|
|
46659
46692
|
import { chmod, lstat as lstat3, mkdir as mkdir6, readFile as readFile5, unlink as unlink5, writeFile as writeFile5 } from "node:fs/promises";
|
|
46660
|
-
import { join as
|
|
46693
|
+
import { join as join26 } from "node:path";
|
|
46661
46694
|
var TTL_MS5 = 15 * 6e4;
|
|
46662
46695
|
var SETUP_TOKEN_FILE = "setup.token";
|
|
46663
46696
|
var BootstrapError = class extends Error {
|
|
46664
46697
|
code = "BOOTSTRAP_PROOF";
|
|
46665
46698
|
};
|
|
46666
|
-
var tokenPath = (home3) =>
|
|
46699
|
+
var tokenPath = (home3) => join26(home3, SETUP_TOKEN_FILE);
|
|
46667
46700
|
async function readStored(home3) {
|
|
46668
46701
|
try {
|
|
46669
46702
|
const info = await lstat3(tokenPath(home3));
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@import"https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Serif:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Mono:ital,wght@0,400;0,500;0,600;1,400&display=swap";:root{--ink-900: #17130c;--ink-800: #241d13;--ink-700: #3a3125;--ink-600: #574b3a;--ink-500: #6f6250;--ink-400: #90826c;--ink-300: #b3a794;--ink-200: #d6ccb9;--bone-000: #fffdf8;--bone-100: #faf6ec;--bone-200: #f2ebdc;--bone-300: #e8dfcc;--bone-400: #dccfb6;--brass-700: #7a5417;--brass-600: #97671f;--brass-500: #b8863b;--brass-400: #cf9d55;--brass-300: #e3c988;--brass-100: #f3e6c4;--brass-050: #faf2df;--wind-700: #2f5560;--wind-600: #3f6e7a;--wind-500: #517f8c;--wind-100: #dbe7ea;--wind-050: #eef4f5;--leaf-600: #4d6b30;--leaf-500: #5f8340;--leaf-100: #e6eed7;--amber-600: #b3771a;--amber-500: #cf8f28;--amber-100: #f7e9c9;--clay-600: #a23b2e;--clay-500: #bd4a3a;--clay-100: #f5dcd6;--term-bg: #1c1810;--term-fg: #e9e0cd;--term-dim: #8f8467;--term-line: #2c2618;--surface-page: var(--bone-100);--surface-panel: var(--bone-200);--surface-card: var(--bone-000);--surface-sunken: var(--bone-200);--surface-inverse: var(--ink-900);--surface-code: var(--term-bg);--text-strong: var(--ink-900);--text-body: var(--ink-700);--text-muted: var(--ink-500);--text-subtle: var(--ink-400);--text-on-brass: var(--ink-900);--text-on-dark: var(--term-fg);--text-link: var(--wind-600);--border-hair: var(--bone-300);--border-strong: var(--bone-400);--border-focus: var(--brass-500);--accent: var(--brass-500);--accent-hover: var(--brass-600);--accent-press: var(--brass-700);--accent-tint: var(--brass-100);--accent-on: var(--ink-900);--info: var(--wind-600);--info-tint: var(--wind-100);--status-ok: var(--leaf-600);--status-ok-tint: var(--leaf-100);--status-warn: var(--amber-600);--status-warn-tint: var(--amber-100);--status-err: var(--clay-600);--status-err-tint: var(--clay-100);--ring: 0 0 0 3px color-mix(in srgb, var(--brass-500) 45%, transparent)}:root{--font-serif: "IBM Plex Serif", Georgia, "Times New Roman", serif;--font-sans: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;--font-display: var(--font-serif);--font-body: var(--font-sans);--font-ui: var(--font-sans);--font-code: var(--font-mono);--text-2xs: 11px;--text-xs: 12px;--text-sm: 13px;--text-md: 14px;--text-base:16px;--text-lg: 18px;--text-xl: 20px;--text-2xl: 24px;--text-3xl: 30px;--text-4xl: 38px;--text-5xl: 48px;--text-6xl: 62px;--weight-regular: 400;--weight-medium: 500;--weight-semibold: 600;--weight-bold: 700;--leading-tight: 1.12;--leading-snug: 1.3;--leading-normal: 1.5;--leading-relaxed:1.65;--tracking-tight: -.02em;--tracking-normal: 0;--tracking-wide: .02em;--tracking-caps: .14em}:root{--space-0: 0;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-7: 32px;--space-8: 40px;--space-9: 48px;--space-10: 64px;--space-11: 80px;--space-12: 96px;--radius-xs: 3px;--radius-sm: 5px;--radius-md: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-pill: 999px;--border-thin: 1px;--border-med: 1.5px;--border-thick:2px;--content-max: 1200px;--sidebar-w: 248px;--topbar-h: 56px;--page-gutter-x: 28px;--page-gutter-y: 24px;--touch-target: 44px;--safe-top: env(safe-area-inset-top, 0px);--safe-right: env(safe-area-inset-right, 0px);--safe-bottom: env(safe-area-inset-bottom, 0px);--safe-left: env(safe-area-inset-left, 0px)}@media (min-width: 768px) and (max-width: 1199px){:root{--sidebar-w: 72px;--page-gutter-x: 20px;--page-gutter-y: 20px}}@media (max-width: 767px){:root{--sidebar-w: 0px;--page-gutter-x: 14px;--page-gutter-y: 14px}}:root{--shadow-xs: 0 1px 1px rgba(35, 27, 15, .05);--shadow-sm: 0 1px 2px rgba(35, 27, 15, .06), 0 1px 1px rgba(35, 27, 15, .04);--shadow-md: 0 2px 4px rgba(35, 27, 15, .07), 0 4px 12px rgba(35, 27, 15, .06);--shadow-lg: 0 8px 24px rgba(35, 27, 15, .1), 0 2px 6px rgba(35, 27, 15, .06);--shadow-xl: 0 20px 48px rgba(35, 27, 15, .16), 0 4px 12px rgba(35, 27, 15, .08);--shadow-inset: inset 0 1px 2px rgba(35, 27, 15, .08);--shadow-gild: 0 1px 0 rgba(255, 253, 248, .6) inset, 0 0 0 1px var(--brass-300);--elevation-flat: none;--elevation-raised: var(--shadow-sm);--elevation-float: var(--shadow-md);--elevation-overlay:var(--shadow-lg);--elevation-modal: var(--shadow-xl);--ease-out: cubic-bezier(.22, .61, .36, 1);--ease-inout: cubic-bezier(.65, 0, .35, 1);--dur-fast: .12s;--dur-base: .18s;--dur-slow: .28s;--dur-pet-active: 2.24s;--dur-pet-attention: 5.04s;--dur-pet-calm: 5.6s;--dur-pet-heavy: 6.72s;--dur-pet-flourish: .84s;--transition-base: all var(--dur-base) var(--ease-out);--transition-fast: all var(--dur-fast) var(--ease-out)}*,*:before,*:after{box-sizing:border-box}body{margin:0;background:var(--surface-page);color:var(--text-body);font-family:var(--font-body);font-size:var(--text-base);line-height:var(--leading-normal);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}h1,h2,h3,h4{font-family:var(--font-display);color:var(--text-strong);line-height:var(--leading-tight);letter-spacing:var(--tracking-tight);font-weight:var(--weight-semibold);margin:0 0 var(--space-3)}p{margin:0 0 var(--space-3)}a{color:var(--text-link);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--text-link) 35%,transparent);transition:var(--transition-fast)}a:hover{color:var(--wind-700);border-bottom-color:var(--wind-700)}code,kbd,samp,pre{font-family:var(--font-code);font-size:.92em}.hn-eyebrow{font-family:var(--font-mono);font-size:var(--text-2xs);font-weight:var(--weight-medium);letter-spacing:var(--tracking-caps);text-transform:uppercase;color:var(--text-muted)}::selection{background:var(--brass-100);color:var(--ink-900)}html,body{margin:0;height:100%;background:var(--surface-page)}#root{height:100vh;height:100dvh;overflow:hidden;max-width:100%}.hn-dynamic-viewport{height:100vh;height:100dvh;min-height:100vh;min-height:100dvh}button:focus-visible,a[href]:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[role=button]:focus-visible,[role=tab]:focus-visible,[role=checkbox]:focus-visible,[role=radio]:focus-visible,[role=switch]:focus-visible{outline:2px solid var(--border-focus)!important;outline-offset:2px}.hn-select select:focus,.hn-select select:focus-visible{outline:none!important}.hn-shell{display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;background:var(--surface-page);color:var(--text-body)}.hn-shell-sidebar{width:var(--sidebar-w);flex:0 0 auto;display:flex;min-height:0;flex-direction:column;box-sizing:border-box;border-right:1px solid var(--border-hair);background:var(--bone-100);padding:18px 14px}.hn-shell-wordmark{padding:2px 4px 20px}.hn-shell-workspace{padding:0 10px 8px}.hn-shell-nav{display:flex;min-height:0;flex-direction:column;gap:2px;overflow-y:auto}.hn-shell-column{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}.hn-shell-topbar{min-height:var(--topbar-h);flex:0 0 auto;display:flex;align-items:center;gap:16px;padding:0 22px;border-bottom:1px solid var(--border-hair);background:color-mix(in srgb,var(--bone-100) 80%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);position:relative;z-index:90}.hn-shell-menu{display:none;width:var(--touch-target);height:var(--touch-target);flex:0 0 auto;align-items:center;justify-content:center;border:1px solid var(--border-hair);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-body)}.hn-shell-heading{min-width:0}.hn-shell-tools{margin-left:auto;display:flex;min-width:0;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:10px}.hn-shell-search{width:220px}.hn-shell-main{flex:1;min-width:0;min-height:0;overflow-x:hidden;overflow-y:auto}.hn-shell-content{width:100%;min-width:0;min-height:100%;margin:0 auto;padding:var(--page-gutter-y) var(--page-gutter-x) calc(32px + var(--safe-bottom));box-sizing:border-box;display:flex;flex-direction:column}.hn-shell-backdrop{display:none}.hn-viewport-popover{box-sizing:border-box;max-width:calc(100vw - var(--safe-left) - var(--safe-right) - 28px)}.hn-modal-overlay{box-sizing:border-box;padding:calc(24px + var(--safe-top)) calc(24px + var(--safe-right)) calc(24px + var(--safe-bottom)) calc(24px + var(--safe-left))}.hn-modal-panel{min-width:0}.hn-modal-footer{flex-wrap:wrap;padding-bottom:calc(14px + var(--safe-bottom))}.hn-board-local-overflow{max-width:100%;overscroll-behavior-inline:contain}.hn-row-actions{flex-wrap:wrap}.hn-topbar-label-short{display:none}.hn-grid-mobile,.hn-stack-mobile,.hn-wrap-mobile,.hn-dense-row,.hn-vps-row{min-width:0}@media (min-width: 768px) and (max-width: 1199px){.hn-shell-sidebar{width:var(--sidebar-w);padding:14px 8px}.hn-shell-sidebar .hn-nav-label,.hn-shell-sidebar .hn-shell-workspace,.hn-shell-sidebar .hn-shell-wordmark>div>div>span:last-child{display:none}.hn-shell-sidebar nav button{justify-content:center;padding-inline:0}.hn-shell-wordmark{display:flex;justify-content:center;padding-inline:0}}@media (max-width: 767px){.hn-shell-menu{display:inline-flex}.hn-shell-sidebar{position:fixed;z-index:120;inset:0 auto 0 0;width:min(320px,calc(100vw - 48px));padding:calc(14px + var(--safe-top)) 14px calc(14px + var(--safe-bottom)) calc(14px + var(--safe-left));box-shadow:var(--shadow-xl);transform:translate(-105%);transition:transform var(--transition-fast)}.hn-shell[data-nav-open=true] .hn-shell-sidebar{transform:translate(0)}.hn-shell-backdrop{display:block;position:fixed;z-index:119;top:0;right:0;bottom:0;left:0;width:100%;height:100%;border:0;background:color-mix(in srgb,var(--ink-900) 42%,transparent)}.hn-shell-topbar{align-items:flex-start;flex-wrap:wrap;gap:8px 10px;padding:calc(6px + var(--safe-top)) var(--page-gutter-x) 8px;-webkit-backdrop-filter:none;backdrop-filter:none}.hn-shell-heading{flex:1 1 calc(100% - 54px);align-self:center}.hn-shell-tools{flex:1 1 100%;margin-left:0;justify-content:flex-start;gap:6px}.hn-shell-search{flex:1 1 100%;width:100%}.hn-topbar-label{display:none}.hn-topbar-label-short{display:inline}.hn-shell button{min-width:var(--touch-target);min-height:var(--touch-target)}.hn-viewport-popover{position:fixed!important;inset:auto max(var(--page-gutter-x),var(--safe-right)) calc(var(--page-gutter-y) + var(--safe-bottom)) max(var(--page-gutter-x),var(--safe-left))!important;width:auto!important;max-width:none;max-height:calc(100dvh - var(--safe-top) - var(--safe-bottom) - var(--page-gutter-y) - var(--page-gutter-y))!important;overflow:auto}.hn-modal-overlay{align-items:flex-end!important;padding:var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left)}.hn-modal-panel{width:100%!important;max-width:100%!important;max-height:calc(100dvh - var(--safe-top) - var(--safe-bottom))!important;border-radius:var(--radius-lg) var(--radius-lg) 0 0!important}.hn-modal-header,.hn-modal-body,.hn-modal-footer{padding-inline:var(--page-gutter-x)!important}.hn-modal-footer>*{min-height:var(--touch-target)}.hn-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}.hn-project-header{display:none!important}.hn-project-row{grid-template-columns:minmax(0,1fr)!important;align-items:stretch!important;gap:10px!important;margin-bottom:10px;padding:14px!important;border:1px solid var(--border-hair);border-left-width:3px;border-radius:var(--radius-md)}.hn-project-row>[data-label]{min-width:0}.hn-project-row>[data-label]:before{content:attr(data-label);display:block;margin-bottom:4px;color:var(--text-subtle);font:var(--weight-semibold) var(--text-2xs)/1.2 var(--font-mono);letter-spacing:.08em;text-transform:uppercase}.hn-project-row>[data-label=Aktivitas]{white-space:normal!important}.hn-backlog-topline,.hn-backlog-view-actions,.hn-backlog-filters{align-items:stretch!important}.hn-backlog-topline>*,.hn-backlog-view-actions>*,.hn-backlog-filters>*{max-width:100%}.hn-backlog-view-actions{flex-wrap:wrap}.hn-backlog-filters .hn-touch-target{flex:1 1 145px!important;width:auto!important}.hn-backlog-grid{grid-template-columns:minmax(0,1fr)!important}.hn-backlog-row{align-items:flex-start!important;flex-wrap:wrap}.hn-backlog-row>div{flex-basis:100%!important}.hn-card-footer{align-items:flex-start!important;flex-direction:column}.hn-grid-mobile{grid-template-columns:minmax(0,1fr)!important}.hn-stack-mobile{align-items:stretch!important;flex-direction:column}.hn-wrap-mobile,.hn-dense-row,.hn-vps-row{align-items:flex-start!important;flex-wrap:wrap}.hn-vps-row>div{flex-basis:calc(100% - 32px)}.hn-vps-row>button{flex:1 1 auto}.hn-dense-row>[style*="flex: 1"]{min-width:min(220px,100%)}.hn-picker-row{flex-wrap:wrap}.hn-picker-row>.hn-picker-title{order:2;flex:1 1 100%!important;min-width:100%!important;white-space:normal!important;overflow:visible!important}.hn-card-header{align-items:stretch!important;flex-direction:column}.hn-card-actions{max-width:100%}.hn-card-actions>*{max-width:100%}.hn-settings-layout{width:100%}.hn-portal-header{height:auto!important;min-height:var(--topbar-h);flex-wrap:wrap;padding:max(8px,var(--safe-top)) max(var(--page-gutter-x),var(--safe-right)) 8px max(var(--page-gutter-x),var(--safe-left))!important}.hn-portal-header>div{flex-basis:1px}.hn-portal-content{box-sizing:border-box;padding:16px max(var(--page-gutter-x),var(--safe-right)) calc(24px + var(--safe-bottom)) max(var(--page-gutter-x),var(--safe-left))!important}.hn-portal-toolbar{align-items:stretch!important;flex-direction:column}.hn-portal-row{align-items:flex-start!important;flex-wrap:wrap;min-height:var(--touch-target)}.hn-portal-row>span:nth-child(2){flex-basis:calc(100% - 110px)}}.hn-responsive-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:10px;min-width:0;max-width:100%}@media (max-width: 767px){.hn-setting-row{align-items:stretch!important;flex-direction:column}.hn-setting-control{width:100%}.hn-setting-control>.hn-touch-target,.hn-setting-control>div{width:100%!important;max-width:100%}.hn-setting-control>div{flex-wrap:wrap}.hn-setting-control>div>div.hn-touch-target{flex:1 1 200px;width:auto!important;max-width:100%}}.hn-local-overflow{max-width:100%;min-width:0;overflow:auto;overscroll-behavior-inline:contain;-webkit-overflow-scrolling:touch}.hn-tabs{max-width:100%;overflow-x:auto;overflow-y:hidden;overscroll-behavior-inline:contain}@media (pointer: coarse),(max-width: 767px){button:not(.hn-shell-backdrop){min-width:var(--touch-target);min-height:var(--touch-target)}input,select,textarea{min-width:var(--touch-target);min-height:var(--touch-target)}.hn-touch-target,.hn-project-open,.hn-terminal-unplaced-action,[role=button][tabindex="0"]{min-width:var(--touch-target)!important;min-height:var(--touch-target)!important}.hn-tabs [role=tab]{min-height:var(--touch-target)}.hn-choice-target{min-width:var(--touch-target);min-height:var(--touch-target)}.hn-choice-control{min-width:var(--touch-target);min-height:var(--touch-target);outline-offset:8px}}.hn-responsive-panels{display:flex;flex:1 1 auto;min-width:0;min-height:0;flex-direction:column;gap:12px}.hn-panel-switcher{flex:0 0 auto;max-width:100%;overflow-x:auto;overscroll-behavior-inline:contain}.hn-panels-grid{display:grid;grid-template-columns:minmax(0,1fr);flex:1 1 auto;min-width:0;min-height:0;gap:16px}.hn-responsive-panel{min-width:0;min-height:0}.hn-panel-flex{display:flex;min-width:0;min-height:0;flex-direction:column}.hn-panel-flex>*{min-width:0}.hn-graph-action{display:inline-grid;min-width:28px;min-height:28px;place-items:center;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text-muted);cursor:pointer}.hn-graph-action:hover{background:var(--bone-200)}.hn-terminal-actions{display:inline-flex;flex:0 0 auto;align-items:center;gap:2px}.hn-terminal-action{display:inline-grid;min-width:28px;min-height:28px;padding:0;place-items:center;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text-subtle);font:inherit;cursor:pointer}.hn-terminal-action--text{padding-inline:5px}.hn-terminal-action:hover{background:var(--bone-300);color:var(--text-strong)}.hn-terminal-keys{display:flex;flex:0 0 auto;gap:4px;max-width:100%;padding:4px 2px;overflow-x:auto;overscroll-behavior-inline:contain;border-top:1px solid var(--border-hair)}.hn-terminal-key{flex:0 0 auto;min-width:40px;min-height:32px;padding:0 8px;border:1px solid var(--border-hair);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-body);font:var(--weight-medium) var(--text-sm)/1 var(--font-mono);cursor:pointer}.hn-terminal-key:hover{background:var(--bone-200);color:var(--text-strong)}@media (max-width: 767px){.hn-terminal-cell-header{flex-wrap:wrap}}@media (pointer: coarse),(max-width: 767px){.hn-graph-action,.hn-terminal-action,.hn-terminal-key,.hn-terminal-group-control{min-width:var(--touch-target);min-height:var(--touch-target)}}.hn-responsive-panel[aria-hidden=true]{display:none}@media (min-width: 768px){.hn-responsive-panels--tablet .hn-panel-switcher{display:none}.hn-responsive-panels--tablet .hn-panels-grid{grid-template-columns:minmax(0,var(--hn-master-width, 280px)) minmax(0,1fr)}.hn-responsive-panels--tablet .hn-responsive-panel[aria-hidden=true]{display:block}}@media (min-width: 1200px){.hn-responsive-panels--desktop .hn-panel-switcher{display:none}.hn-responsive-panels--desktop .hn-panels-grid{grid-template-columns:minmax(0,var(--hn-master-width, 300px)) minmax(0,1fr)}.hn-responsive-panels--desktop .hn-responsive-panel[aria-hidden=true]{display:block}}@media (prefers-reduced-motion: reduce){*,*:before,*:after{animation:none!important;scroll-behavior:auto!important;transition:none!important}}button{--accent-on: #fff}a{color:var(--text-link);text-decoration:none}a:hover{color:var(--wind-700);text-decoration:underline}.hn-md{color:var(--text-body);font-family:var(--font-sans);font-size:15px;line-height:1.72;overflow-wrap:anywhere}.hn-md>:first-child{margin-top:8px}.hn-md h1,.hn-md h2,.hn-md h3,.hn-md h4{font-family:var(--font-display);font-weight:600;letter-spacing:-.02em;color:var(--ink-900);line-height:1.2;margin:1.6em 0 .5em}.hn-md h1{font-size:30px;margin-top:.4em;padding-bottom:.34em;border-bottom:1px solid var(--border-hair)}.hn-md h2{font-size:22px}.hn-md h3{font-size:18px}.hn-md h4{font-size:15px}.hn-md p{margin:.7em 0}.hn-md ul,.hn-md ol{margin:.6em 0;padding-left:1.5em}.hn-md li{margin:.28em 0}.hn-md li::marker{color:var(--brass-500)}.hn-md ul.contains-task-list,.hn-md li.task-list-item{list-style:none}.hn-md li.task-list-item{padding-left:0}.hn-md input[type=checkbox]{accent-color:var(--brass-500);margin-right:8px;transform:translateY(1px)}.hn-md strong{font-weight:600;color:var(--ink-900)}.hn-md em{color:var(--text-muted)}.hn-md a{color:var(--text-link)}.hn-md hr{border:none;border-top:1px solid var(--border-hair);margin:1.6em 0}.hn-md code{font-family:var(--font-mono);font-size:.86em;background:var(--bone-200);color:var(--ink-800);padding:1.5px 5px;border-radius:var(--radius-xs);border:1px solid var(--border-hair)}.hn-md pre{background:var(--surface-code);border:1px solid var(--term-line);border-radius:var(--radius-lg);padding:14px 16px;overflow:auto;margin:1em 0;white-space:pre-wrap;overflow-wrap:anywhere}.hn-md pre code{background:transparent;border:none;padding:0;color:var(--term-fg);font-size:12.5px;line-height:1.7}.hn-md blockquote{margin:1em 0;padding:4px 16px;border-left:3px solid var(--brass-500);background:var(--brass-050);color:var(--text-body);border-radius:0 var(--radius-sm) var(--radius-sm) 0}.hn-md blockquote p{margin:.4em 0}.hn-md table{border-collapse:collapse;width:100%;margin:1em 0;font-size:14px;table-layout:fixed}.hn-md th,.hn-md td{overflow-wrap:anywhere}.hn-md th{font-family:var(--font-mono);font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-muted);text-align:left;padding:8px 12px;background:var(--bone-100);border:1px solid var(--border-hair)}.hn-md td{padding:8px 12px;border:1px solid var(--border-hair);color:var(--text-body)}.hn-md td code{font-size:.82em}.hn-md img{max-width:100%;border-radius:var(--radius-sm)}@keyframes hn-fade-in{0%{opacity:0}to{opacity:1}}@keyframes hn-modal-in{0%{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:none}}@keyframes hn-toast-in{0%{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%)}}.hn-pet-reactor{transform-origin:50% 86%}.hn-pet-stage:not([data-reduced-motion=true]):hover .hn-pet-reactor{transform:translateY(-2px) scale(1.035) rotate(-1deg)}@keyframes hn-pet-idle-ready{0%,to{transform:translateY(0) scale(1)}50%{transform:translateY(-2px) scale(1.018)}}@keyframes hn-pet-idle-working{0%,to{transform:translateY(0) rotate(0) scale(1)}20%{transform:translateY(-2px) rotate(-.8deg) scale(1.018)}40%{transform:translateY(0) rotate(.6deg) scale(1)}60%{transform:translateY(-3px) rotate(-.5deg) scale(1.022)}80%{transform:translateY(-1px) rotate(.4deg) scale(1.008)}}@keyframes hn-pet-idle-waiting{0%,64%,to{transform:translateY(0) rotate(0)}70%{transform:translateY(-1px) rotate(-2deg)}76%{transform:translateY(-2px) rotate(3deg)}82%{transform:translateY(-1px) rotate(-2deg)}88%{transform:translateY(0) rotate(0)}}@keyframes hn-pet-idle-blocked{0%,to{transform:translateY(1px) scaleY(.99)}50%{transform:translateY(3px) scale(.99,.97)}}@keyframes hn-pet-idle-review{0%,64%,to{transform:translateY(0) rotate(0) scale(1)}74%{transform:translateY(-1px) rotate(-1.6deg) scale(1.012)}84%{transform:translateY(-1px) rotate(.8deg) scale(1.006)}}@keyframes hn-pet-idle-shipped{0%,to{transform:translateY(0) scale(1)}50%{transform:translateY(-2px) scale(1.015)}}@keyframes hn-pet-idle-docs{0%,66%,to{transform:translateY(0) rotate(0) scale(1)}72%{transform:translateY(-1px) rotate(-1.8deg) scale(1.01)}78%{transform:translateY(-1px) rotate(1.5deg) scale(1.012)}84%{transform:translateY(0) rotate(-.7deg) scale(1)}}@keyframes hn-pet-celebrate{0%{transform:translateY(3px) scale(.92) rotate(0)}38%{transform:translateY(-5px) scale(1.08) rotate(-3deg)}62%{transform:translateY(-2px) scale(1.03) rotate(3deg)}to{transform:translateY(0) scale(1) rotate(0)}}@keyframes hn-pet-pose-in{0%{opacity:0;transform:translateY(4px) scale(.76,.92)}62%{opacity:1;transform:translateY(-2px) scale(1.07,.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes hn-pet-pose-out{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(3px) scale(.86,1.04)}}@keyframes hn-pet-click{0%,to{transform:translateY(0) scale(1) rotate(0)}38%{transform:translateY(2px) scale(.9,1.06) rotate(-2deg)}72%{transform:translateY(-3px) scale(1.06,.96) rotate(1.5deg)}}@keyframes hn-pet-panel-in{0%{opacity:0;transform:translateY(6px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes hn-pet-panel-out{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(5px) scale(.985)}}@keyframes hn-pet-reveal{0%{opacity:0;transform:translateY(7px) scale(.86)}70%{opacity:1;transform:translateY(-1px) scale(1.035)}to{opacity:1;transform:translateY(0) scale(1)}}/**
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Serif:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Mono:ital,wght@0,400;0,500;0,600;1,400&display=swap";:root{--ink-900: #17130c;--ink-800: #241d13;--ink-700: #3a3125;--ink-600: #574b3a;--ink-500: #6f6250;--ink-400: #90826c;--ink-300: #b3a794;--ink-200: #d6ccb9;--bone-000: #fffdf8;--bone-100: #faf6ec;--bone-200: #f2ebdc;--bone-300: #e8dfcc;--bone-400: #dccfb6;--brass-700: #7a5417;--brass-600: #97671f;--brass-500: #b8863b;--brass-400: #cf9d55;--brass-300: #e3c988;--brass-100: #f3e6c4;--brass-050: #faf2df;--wind-700: #2f5560;--wind-600: #3f6e7a;--wind-500: #517f8c;--wind-100: #dbe7ea;--wind-050: #eef4f5;--leaf-600: #4d6b30;--leaf-500: #5f8340;--leaf-100: #e6eed7;--amber-600: #b3771a;--amber-500: #cf8f28;--amber-100: #f7e9c9;--clay-600: #a23b2e;--clay-500: #bd4a3a;--clay-100: #f5dcd6;--term-bg: #1c1810;--term-fg: #e9e0cd;--term-dim: #8f8467;--term-line: #2c2618;--surface-page: var(--bone-100);--surface-panel: var(--bone-200);--surface-card: var(--bone-000);--surface-sunken: var(--bone-200);--surface-inverse: var(--ink-900);--surface-code: var(--term-bg);--text-strong: var(--ink-900);--text-body: var(--ink-700);--text-muted: var(--ink-500);--text-subtle: var(--ink-400);--text-on-brass: var(--ink-900);--text-on-dark: var(--term-fg);--text-link: var(--wind-600);--border-hair: var(--bone-300);--border-strong: var(--bone-400);--border-focus: var(--brass-500);--accent: var(--brass-500);--accent-hover: var(--brass-600);--accent-press: var(--brass-700);--accent-tint: var(--brass-100);--accent-on: var(--ink-900);--info: var(--wind-600);--info-tint: var(--wind-100);--status-ok: var(--leaf-600);--status-ok-tint: var(--leaf-100);--status-warn: var(--amber-600);--status-warn-tint: var(--amber-100);--status-err: var(--clay-600);--status-err-tint: var(--clay-100);--ring: 0 0 0 3px color-mix(in srgb, var(--brass-500) 45%, transparent)}:root{--font-serif: "IBM Plex Serif", Georgia, "Times New Roman", serif;--font-sans: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;--font-display: var(--font-serif);--font-body: var(--font-sans);--font-ui: var(--font-sans);--font-code: var(--font-mono);--text-2xs: 11px;--text-xs: 12px;--text-sm: 13px;--text-md: 14px;--text-base:16px;--text-lg: 18px;--text-xl: 20px;--text-2xl: 24px;--text-3xl: 30px;--text-4xl: 38px;--text-5xl: 48px;--text-6xl: 62px;--weight-regular: 400;--weight-medium: 500;--weight-semibold: 600;--weight-bold: 700;--leading-tight: 1.12;--leading-snug: 1.3;--leading-normal: 1.5;--leading-relaxed:1.65;--tracking-tight: -.02em;--tracking-normal: 0;--tracking-wide: .02em;--tracking-caps: .14em}:root{--space-0: 0;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-7: 32px;--space-8: 40px;--space-9: 48px;--space-10: 64px;--space-11: 80px;--space-12: 96px;--radius-xs: 3px;--radius-sm: 5px;--radius-md: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-pill: 999px;--border-thin: 1px;--border-med: 1.5px;--border-thick:2px;--content-max: 1200px;--sidebar-w: 248px;--topbar-h: 56px;--page-gutter-x: 28px;--page-gutter-y: 24px;--touch-target: 44px;--safe-top: env(safe-area-inset-top, 0px);--safe-right: env(safe-area-inset-right, 0px);--safe-bottom: env(safe-area-inset-bottom, 0px);--safe-left: env(safe-area-inset-left, 0px)}@media (min-width: 768px) and (max-width: 1199px){:root{--sidebar-w: 72px;--page-gutter-x: 20px;--page-gutter-y: 20px}}@media (max-width: 767px){:root{--sidebar-w: 0px;--page-gutter-x: 14px;--page-gutter-y: 14px}}:root{--shadow-xs: 0 1px 1px rgba(35, 27, 15, .05);--shadow-sm: 0 1px 2px rgba(35, 27, 15, .06), 0 1px 1px rgba(35, 27, 15, .04);--shadow-md: 0 2px 4px rgba(35, 27, 15, .07), 0 4px 12px rgba(35, 27, 15, .06);--shadow-lg: 0 8px 24px rgba(35, 27, 15, .1), 0 2px 6px rgba(35, 27, 15, .06);--shadow-xl: 0 20px 48px rgba(35, 27, 15, .16), 0 4px 12px rgba(35, 27, 15, .08);--shadow-inset: inset 0 1px 2px rgba(35, 27, 15, .08);--shadow-gild: 0 1px 0 rgba(255, 253, 248, .6) inset, 0 0 0 1px var(--brass-300);--elevation-flat: none;--elevation-raised: var(--shadow-sm);--elevation-float: var(--shadow-md);--elevation-overlay:var(--shadow-lg);--elevation-modal: var(--shadow-xl);--ease-out: cubic-bezier(.22, .61, .36, 1);--ease-inout: cubic-bezier(.65, 0, .35, 1);--dur-fast: .12s;--dur-base: .18s;--dur-slow: .28s;--dur-pet-active: 2.24s;--dur-pet-attention: 5.04s;--dur-pet-calm: 5.6s;--dur-pet-heavy: 6.72s;--dur-pet-flourish: .84s;--transition-base: all var(--dur-base) var(--ease-out);--transition-fast: all var(--dur-fast) var(--ease-out)}*,*:before,*:after{box-sizing:border-box}body{margin:0;background:var(--surface-page);color:var(--text-body);font-family:var(--font-body);font-size:var(--text-base);line-height:var(--leading-normal);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}h1,h2,h3,h4{font-family:var(--font-display);color:var(--text-strong);line-height:var(--leading-tight);letter-spacing:var(--tracking-tight);font-weight:var(--weight-semibold);margin:0 0 var(--space-3)}p{margin:0 0 var(--space-3)}a{color:var(--text-link);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--text-link) 35%,transparent);transition:var(--transition-fast)}a:hover{color:var(--wind-700);border-bottom-color:var(--wind-700)}code,kbd,samp,pre{font-family:var(--font-code);font-size:.92em}.hn-eyebrow{font-family:var(--font-mono);font-size:var(--text-2xs);font-weight:var(--weight-medium);letter-spacing:var(--tracking-caps);text-transform:uppercase;color:var(--text-muted)}::selection{background:var(--brass-100);color:var(--ink-900)}html,body{margin:0;height:100%;background:var(--surface-page)}#root{height:100vh;height:100dvh;overflow:hidden;max-width:100%}.hn-dynamic-viewport{height:100vh;height:100dvh;min-height:100vh;min-height:100dvh}button:focus-visible,a[href]:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[role=button]:focus-visible,[role=tab]:focus-visible,[role=checkbox]:focus-visible,[role=radio]:focus-visible,[role=switch]:focus-visible{outline:2px solid var(--border-focus)!important;outline-offset:2px}.hn-select select:focus,.hn-select select:focus-visible{outline:none!important}.hn-shell{display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;background:var(--surface-page);color:var(--text-body)}.hn-shell-sidebar{width:var(--sidebar-w);flex:0 0 auto;display:flex;min-height:0;flex-direction:column;box-sizing:border-box;border-right:1px solid var(--border-hair);background:var(--bone-100);padding:18px 14px}.hn-shell-wordmark{padding:2px 4px 20px}.hn-shell-workspace{padding:0 10px 8px}.hn-shell-nav{display:flex;min-height:0;flex-direction:column;gap:2px;overflow-y:auto}.hn-shell-column{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}.hn-shell-topbar{min-height:var(--topbar-h);flex:0 0 auto;display:flex;align-items:center;gap:16px;padding:0 22px;border-bottom:1px solid var(--border-hair);background:color-mix(in srgb,var(--bone-100) 80%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);position:relative;z-index:90}.hn-shell-menu{display:none;width:var(--touch-target);height:var(--touch-target);flex:0 0 auto;align-items:center;justify-content:center;border:1px solid var(--border-hair);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-body)}.hn-shell-heading{min-width:0}.hn-shell-tools{margin-left:auto;display:flex;min-width:0;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:10px}.hn-shell-search{width:220px}.hn-shell-main{flex:1;min-width:0;min-height:0;overflow-x:hidden;overflow-y:auto}.hn-shell-content{width:100%;min-width:0;min-height:100%;margin:0 auto;padding:var(--page-gutter-y) var(--page-gutter-x) calc(32px + var(--safe-bottom));box-sizing:border-box;display:flex;flex-direction:column}.hn-shell-backdrop{display:none}.hn-viewport-popover{box-sizing:border-box;max-width:calc(100vw - var(--safe-left) - var(--safe-right) - 28px)}.hn-modal-overlay{box-sizing:border-box;padding:calc(24px + var(--safe-top)) calc(24px + var(--safe-right)) calc(24px + var(--safe-bottom)) calc(24px + var(--safe-left))}.hn-modal-panel{min-width:0}.hn-modal-footer{flex-wrap:wrap;padding-bottom:calc(14px + var(--safe-bottom))}.hn-board-local-overflow{max-width:100%;overscroll-behavior-inline:contain}.hn-row-actions{flex-wrap:wrap}.hn-topbar-label-short{display:none}.hn-grid-mobile,.hn-stack-mobile,.hn-wrap-mobile,.hn-dense-row,.hn-vps-row{min-width:0}@media (min-width: 768px) and (max-width: 1199px){.hn-shell-sidebar{width:var(--sidebar-w);padding:14px 8px}.hn-shell-sidebar .hn-nav-label,.hn-shell-sidebar .hn-shell-workspace,.hn-shell-sidebar .hn-shell-wordmark>div>div>span:last-child{display:none}.hn-shell-sidebar nav button{justify-content:center;padding-inline:0}.hn-shell-wordmark{display:flex;justify-content:center;padding-inline:0}}@media (max-width: 767px){.hn-shell-menu{display:inline-flex}.hn-shell-sidebar{position:fixed;z-index:120;inset:0 auto 0 0;width:min(320px,calc(100vw - 48px));padding:calc(14px + var(--safe-top)) 14px calc(14px + var(--safe-bottom)) calc(14px + var(--safe-left));box-shadow:var(--shadow-xl);transform:translate(-105%);transition:transform var(--transition-fast)}.hn-shell[data-nav-open=true] .hn-shell-sidebar{transform:translate(0)}.hn-shell-backdrop{display:block;position:fixed;z-index:119;top:0;right:0;bottom:0;left:0;width:100%;height:100%;border:0;background:color-mix(in srgb,var(--ink-900) 42%,transparent)}.hn-shell-topbar{align-items:flex-start;flex-wrap:wrap;gap:8px 10px;padding:calc(6px + var(--safe-top)) var(--page-gutter-x) 8px;-webkit-backdrop-filter:none;backdrop-filter:none}.hn-shell-heading{flex:1 1 calc(100% - 54px);align-self:center}.hn-shell-tools{flex:1 1 100%;margin-left:0;justify-content:flex-start;gap:6px}.hn-shell-search{flex:1 1 100%;width:100%}.hn-topbar-label{display:none}.hn-topbar-label-short{display:inline}.hn-shell button{min-width:var(--touch-target);min-height:var(--touch-target)}.hn-viewport-popover{position:fixed!important;inset:auto max(var(--page-gutter-x),var(--safe-right)) calc(var(--page-gutter-y) + var(--safe-bottom)) max(var(--page-gutter-x),var(--safe-left))!important;width:auto!important;max-width:none;max-height:calc(100dvh - var(--safe-top) - var(--safe-bottom) - var(--page-gutter-y) - var(--page-gutter-y))!important;overflow:auto}.hn-modal-overlay{align-items:flex-end!important;padding:var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left)}.hn-modal-panel{width:100%!important;max-width:100%!important;max-height:calc(100dvh - var(--safe-top) - var(--safe-bottom))!important;border-radius:var(--radius-lg) var(--radius-lg) 0 0!important}.hn-modal-header,.hn-modal-body,.hn-modal-footer{padding-inline:var(--page-gutter-x)!important}.hn-modal-footer>*{min-height:var(--touch-target)}.hn-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important}.hn-project-header{display:none!important}.hn-project-row{grid-template-columns:minmax(0,1fr)!important;align-items:stretch!important;gap:10px!important;margin-bottom:10px;padding:14px!important;border:1px solid var(--border-hair);border-left-width:3px;border-radius:var(--radius-md)}.hn-project-row>[data-label]{min-width:0}.hn-project-row>[data-label]:before{content:attr(data-label);display:block;margin-bottom:4px;color:var(--text-subtle);font:var(--weight-semibold) var(--text-2xs)/1.2 var(--font-mono);letter-spacing:.08em;text-transform:uppercase}.hn-project-row>[data-label=Aktivitas]{white-space:normal!important}.hn-backlog-topline,.hn-backlog-view-actions,.hn-backlog-filters{align-items:stretch!important}.hn-backlog-topline>*,.hn-backlog-view-actions>*,.hn-backlog-filters>*{max-width:100%}.hn-backlog-view-actions{flex-wrap:wrap}.hn-backlog-filters .hn-touch-target{flex:1 1 145px!important;width:auto!important}.hn-backlog-grid{grid-template-columns:minmax(0,1fr)!important}.hn-backlog-row{align-items:flex-start!important;flex-wrap:wrap}.hn-backlog-row>div{flex-basis:100%!important}.hn-card-footer{align-items:flex-start!important;flex-direction:column}.hn-grid-mobile{grid-template-columns:minmax(0,1fr)!important}.hn-stack-mobile{align-items:stretch!important;flex-direction:column}.hn-wrap-mobile,.hn-dense-row,.hn-vps-row{align-items:flex-start!important;flex-wrap:wrap}.hn-vps-row>div{flex-basis:calc(100% - 32px)}.hn-vps-row>button{flex:1 1 auto}.hn-dense-row>[style*="flex: 1"]{min-width:min(220px,100%)}.hn-picker-row{flex-wrap:wrap}.hn-picker-row>.hn-picker-title{order:2;flex:1 1 100%!important;min-width:100%!important;white-space:normal!important;overflow:visible!important}.hn-card-header{align-items:stretch!important;flex-direction:column}.hn-card-actions{max-width:100%}.hn-card-actions>*{max-width:100%}.hn-settings-layout{width:100%}.hn-portal-header{height:auto!important;min-height:var(--topbar-h);flex-wrap:wrap;padding:max(8px,var(--safe-top)) max(var(--page-gutter-x),var(--safe-right)) 8px max(var(--page-gutter-x),var(--safe-left))!important}.hn-portal-header>div{flex-basis:1px}.hn-portal-content{box-sizing:border-box;padding:16px max(var(--page-gutter-x),var(--safe-right)) calc(24px + var(--safe-bottom)) max(var(--page-gutter-x),var(--safe-left))!important}.hn-portal-toolbar{align-items:stretch!important;flex-direction:column}.hn-portal-row{align-items:flex-start!important;flex-wrap:wrap;min-height:var(--touch-target)}.hn-portal-row>span:nth-child(2){flex-basis:calc(100% - 110px)}}.hn-responsive-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:10px;min-width:0;max-width:100%}@media (max-width: 767px){.hn-setting-row{align-items:stretch!important;flex-direction:column}.hn-setting-control{width:100%}.hn-setting-control>.hn-touch-target,.hn-setting-control>div{width:100%!important;max-width:100%}.hn-setting-control>div{flex-wrap:wrap}.hn-setting-control>div>div.hn-touch-target{flex:1 1 200px;width:auto!important;max-width:100%}}.hn-local-overflow{max-width:100%;min-width:0;overflow:auto;overscroll-behavior-inline:contain;-webkit-overflow-scrolling:touch}.hn-tabs{max-width:100%;overflow-x:auto;overflow-y:hidden;overscroll-behavior-inline:contain}.hn-ide-head{display:flex;align-items:center;flex-wrap:wrap;gap:12px;min-width:0}.hn-ide-head>.hn-tabs{flex:0 0 auto}.hn-ide-toolbar{display:flex;align-items:center;flex:1 1 480px;flex-wrap:nowrap;gap:10px;min-width:0;max-width:100%;overflow-x:auto;overflow-y:hidden;overscroll-behavior-inline:contain}.hn-ide-toolbar>*{flex:0 0 auto}.hn-ide-toolbar>:first-child{margin-inline-start:auto}@media (pointer: coarse),(max-width: 767px){button:not(.hn-shell-backdrop){min-width:var(--touch-target);min-height:var(--touch-target)}input,select,textarea{min-width:var(--touch-target);min-height:var(--touch-target)}.hn-touch-target,.hn-project-open,.hn-terminal-unplaced-action,[role=button][tabindex="0"]{min-width:var(--touch-target)!important;min-height:var(--touch-target)!important}.hn-tabs [role=tab]{min-height:var(--touch-target)}.hn-choice-target{min-width:var(--touch-target);min-height:var(--touch-target)}.hn-choice-control{min-width:var(--touch-target);min-height:var(--touch-target);outline-offset:8px}}.hn-responsive-panels{display:flex;flex:1 1 auto;min-width:0;min-height:0;flex-direction:column;gap:12px}.hn-panel-switcher{flex:0 0 auto;max-width:100%;overflow-x:auto;overscroll-behavior-inline:contain}.hn-panels-grid{display:grid;grid-template-columns:minmax(0,1fr);flex:1 1 auto;min-width:0;min-height:0;gap:16px}.hn-responsive-panel{min-width:0;min-height:0}.hn-panel-flex{display:flex;min-width:0;min-height:0;flex-direction:column}.hn-panel-flex>*{min-width:0}.hn-graph-action{display:inline-grid;min-width:28px;min-height:28px;place-items:center;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text-muted);cursor:pointer}.hn-graph-action:hover{background:var(--bone-200)}.hn-terminal-actions{display:inline-flex;flex:0 0 auto;align-items:center;gap:2px}.hn-terminal-action{display:inline-grid;min-width:28px;min-height:28px;padding:0;place-items:center;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text-subtle);font:inherit;cursor:pointer}.hn-terminal-action--text{padding-inline:5px}.hn-terminal-action:hover{background:var(--bone-300);color:var(--text-strong)}.hn-terminal-keys{display:flex;flex:0 0 auto;gap:4px;max-width:100%;padding:4px 2px;overflow-x:auto;overscroll-behavior-inline:contain;border-top:1px solid var(--border-hair)}.hn-terminal-key{flex:0 0 auto;min-width:40px;min-height:32px;padding:0 8px;border:1px solid var(--border-hair);border-radius:var(--radius-sm);background:var(--surface-card);color:var(--text-body);font:var(--weight-medium) var(--text-sm)/1 var(--font-mono);cursor:pointer}.hn-terminal-key:hover{background:var(--bone-200);color:var(--text-strong)}@media (max-width: 767px){.hn-terminal-cell-header{flex-wrap:wrap}}@media (pointer: coarse),(max-width: 767px){.hn-graph-action,.hn-terminal-action,.hn-terminal-key,.hn-terminal-group-control{min-width:var(--touch-target);min-height:var(--touch-target)}}.hn-responsive-panel[aria-hidden=true]{display:none}@media (min-width: 768px){.hn-responsive-panels--tablet .hn-panel-switcher{display:none}.hn-responsive-panels--tablet .hn-panels-grid{grid-template-columns:minmax(0,var(--hn-master-width, 280px)) minmax(0,1fr)}.hn-responsive-panels--tablet .hn-responsive-panel[aria-hidden=true]{display:block}}@media (min-width: 1200px){.hn-responsive-panels--desktop .hn-panel-switcher{display:none}.hn-responsive-panels--desktop .hn-panels-grid{grid-template-columns:minmax(0,var(--hn-master-width, 300px)) minmax(0,1fr)}.hn-responsive-panels--desktop .hn-responsive-panel[aria-hidden=true]{display:block}}@media (prefers-reduced-motion: reduce){*,*:before,*:after{animation:none!important;scroll-behavior:auto!important;transition:none!important}}button{--accent-on: #fff}a{color:var(--text-link);text-decoration:none}a:hover{color:var(--wind-700);text-decoration:underline}.hn-md{color:var(--text-body);font-family:var(--font-sans);font-size:15px;line-height:1.72;overflow-wrap:anywhere}.hn-md>:first-child{margin-top:8px}.hn-md h1,.hn-md h2,.hn-md h3,.hn-md h4{font-family:var(--font-display);font-weight:600;letter-spacing:-.02em;color:var(--ink-900);line-height:1.2;margin:1.6em 0 .5em}.hn-md h1{font-size:30px;margin-top:.4em;padding-bottom:.34em;border-bottom:1px solid var(--border-hair)}.hn-md h2{font-size:22px}.hn-md h3{font-size:18px}.hn-md h4{font-size:15px}.hn-md p{margin:.7em 0}.hn-md ul,.hn-md ol{margin:.6em 0;padding-left:1.5em}.hn-md li{margin:.28em 0}.hn-md li::marker{color:var(--brass-500)}.hn-md ul.contains-task-list,.hn-md li.task-list-item{list-style:none}.hn-md li.task-list-item{padding-left:0}.hn-md input[type=checkbox]{accent-color:var(--brass-500);margin-right:8px;transform:translateY(1px)}.hn-md strong{font-weight:600;color:var(--ink-900)}.hn-md em{color:var(--text-muted)}.hn-md a{color:var(--text-link)}.hn-md hr{border:none;border-top:1px solid var(--border-hair);margin:1.6em 0}.hn-md code{font-family:var(--font-mono);font-size:.86em;background:var(--bone-200);color:var(--ink-800);padding:1.5px 5px;border-radius:var(--radius-xs);border:1px solid var(--border-hair)}.hn-md pre{background:var(--surface-code);border:1px solid var(--term-line);border-radius:var(--radius-lg);padding:14px 16px;overflow:auto;margin:1em 0;white-space:pre-wrap;overflow-wrap:anywhere}.hn-md pre code{background:transparent;border:none;padding:0;color:var(--term-fg);font-size:12.5px;line-height:1.7}.hn-md blockquote{margin:1em 0;padding:4px 16px;border-left:3px solid var(--brass-500);background:var(--brass-050);color:var(--text-body);border-radius:0 var(--radius-sm) var(--radius-sm) 0}.hn-md blockquote p{margin:.4em 0}.hn-md table{border-collapse:collapse;width:100%;margin:1em 0;font-size:14px;table-layout:fixed}.hn-md th,.hn-md td{overflow-wrap:anywhere}.hn-md th{font-family:var(--font-mono);font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-muted);text-align:left;padding:8px 12px;background:var(--bone-100);border:1px solid var(--border-hair)}.hn-md td{padding:8px 12px;border:1px solid var(--border-hair);color:var(--text-body)}.hn-md td code{font-size:.82em}.hn-md img{max-width:100%;border-radius:var(--radius-sm)}@keyframes hn-fade-in{0%{opacity:0}to{opacity:1}}@keyframes hn-modal-in{0%{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:none}}@keyframes hn-toast-in{0%{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%)}}.hn-pet-reactor{transform-origin:50% 86%}.hn-pet-stage:not([data-reduced-motion=true]):hover .hn-pet-reactor{transform:translateY(-2px) scale(1.035) rotate(-1deg)}@keyframes hn-pet-idle-ready{0%,to{transform:translateY(0) scale(1)}50%{transform:translateY(-2px) scale(1.018)}}@keyframes hn-pet-idle-working{0%,to{transform:translateY(0) rotate(0) scale(1)}20%{transform:translateY(-2px) rotate(-.8deg) scale(1.018)}40%{transform:translateY(0) rotate(.6deg) scale(1)}60%{transform:translateY(-3px) rotate(-.5deg) scale(1.022)}80%{transform:translateY(-1px) rotate(.4deg) scale(1.008)}}@keyframes hn-pet-idle-waiting{0%,64%,to{transform:translateY(0) rotate(0)}70%{transform:translateY(-1px) rotate(-2deg)}76%{transform:translateY(-2px) rotate(3deg)}82%{transform:translateY(-1px) rotate(-2deg)}88%{transform:translateY(0) rotate(0)}}@keyframes hn-pet-idle-blocked{0%,to{transform:translateY(1px) scaleY(.99)}50%{transform:translateY(3px) scale(.99,.97)}}@keyframes hn-pet-idle-review{0%,64%,to{transform:translateY(0) rotate(0) scale(1)}74%{transform:translateY(-1px) rotate(-1.6deg) scale(1.012)}84%{transform:translateY(-1px) rotate(.8deg) scale(1.006)}}@keyframes hn-pet-idle-shipped{0%,to{transform:translateY(0) scale(1)}50%{transform:translateY(-2px) scale(1.015)}}@keyframes hn-pet-idle-docs{0%,66%,to{transform:translateY(0) rotate(0) scale(1)}72%{transform:translateY(-1px) rotate(-1.8deg) scale(1.01)}78%{transform:translateY(-1px) rotate(1.5deg) scale(1.012)}84%{transform:translateY(0) rotate(-.7deg) scale(1)}}@keyframes hn-pet-celebrate{0%{transform:translateY(3px) scale(.92) rotate(0)}38%{transform:translateY(-5px) scale(1.08) rotate(-3deg)}62%{transform:translateY(-2px) scale(1.03) rotate(3deg)}to{transform:translateY(0) scale(1) rotate(0)}}@keyframes hn-pet-pose-in{0%{opacity:0;transform:translateY(4px) scale(.76,.92)}62%{opacity:1;transform:translateY(-2px) scale(1.07,.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes hn-pet-pose-out{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(3px) scale(.86,1.04)}}@keyframes hn-pet-click{0%,to{transform:translateY(0) scale(1) rotate(0)}38%{transform:translateY(2px) scale(.9,1.06) rotate(-2deg)}72%{transform:translateY(-3px) scale(1.06,.96) rotate(1.5deg)}}@keyframes hn-pet-panel-in{0%{opacity:0;transform:translateY(6px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes hn-pet-panel-out{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(5px) scale(.985)}}@keyframes hn-pet-reveal{0%{opacity:0;transform:translateY(7px) scale(.86)}70%{opacity:1;transform:translateY(-1px) scale(1.035)}to{opacity:1;transform:translateY(0) scale(1)}}/**
|
|
2
2
|
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
3
|
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
4
|
* https://github.com/chjj/term.js
|