hanoman 0.9.36 → 0.9.37
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 +3 -3
- package/dist/cli.js +11 -2
- package/dist/server.js +43 -12
- package/docs/agent-integration.md +4 -0
- package/package.json +1 -1
- package/web/assets/{DalangHanomanScreen-NmpJIcg6.js → DalangHanomanScreen-JE8gkztH.js} +1 -1
- package/web/assets/{DocPreviewModal-DK597e3s.js → DocPreviewModal-B23vI_It.js} +1 -1
- package/web/assets/{DocsWorkspace-BQX-HlzW.js → DocsWorkspace-CbV27H6A.js} +1 -1
- package/web/assets/{IdeScreen-LeUPaFsS.js → IdeScreen-BY7sm97W.js} +1 -1
- package/web/assets/{LeadScreen-BVCKv46y.js → LeadScreen-BFwI29zS.js} +1 -1
- package/web/assets/{ReviewScreen-C6NcJChq.js → ReviewScreen-pM6zzGZl.js} +1 -1
- package/web/assets/{SchedulerScreen-2AH0R3TJ.js → SchedulerScreen-BIhqn3X1.js} +1 -1
- package/web/assets/{SettingsScreen-B4SVzh9m.js → SettingsScreen-C_TW3mbs.js} +1 -1
- package/web/assets/{TeamScreen-6XEfuZUm.js → TeamScreen-RT926lDf.js} +1 -1
- package/web/assets/TerminalScreen-fpC5a2jS.js +2 -0
- package/web/assets/{TriageScreen-BYJxyCar.js → TriageScreen-Zp1bdRnl.js} +1 -1
- package/web/assets/{VpsScreen-Df37dgKx.js → VpsScreen-Jnb8C1o2.js} +2 -2
- package/web/assets/{fields-C94HI0V8.js → fields-B_3dIGcG.js} +1 -1
- package/web/assets/{index-BeFSh2Ba.js → index-CbX7iwxN.js} +27 -27
- package/web/assets/{live-5ezoV9Fs.js → live-CNp86nGW.js} +1 -1
- package/web/assets/{sched-lead-shared-BpZu6N2A.js → sched-lead-shared-BUcJMfNH.js} +1 -1
- package/web/assets/{settings-rebase-DaTGgcuO.js → settings-rebase-CYr7W_rB.js} +1 -1
- package/web/index.html +1 -1
- package/web/assets/TerminalScreen-DubD6vT-.js +0 -2
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -7234,7 +7234,13 @@ var init_dto = __esm({
|
|
|
7234
7234
|
agent: zAgent.optional(),
|
|
7235
7235
|
model: external_exports.string().optional(),
|
|
7236
7236
|
effort: external_exports.string().optional(),
|
|
7237
|
-
force: external_exports.boolean().optional()
|
|
7237
|
+
force: external_exports.boolean().optional(),
|
|
7238
|
+
// ADR-0232 · opsional: `worktree:true` → sesi lahir di `.worktrees/<id>` pada branch baru
|
|
7239
|
+
// `term/<id>` dari `branchFrom` (kosong → HEAD repo), alih-alih langsung di repoDir. Tanpa
|
|
7240
|
+
// keduanya body-nya byte-identik dengan sebelumnya. `branchFrom` tanpa `worktree` ditolak di
|
|
7241
|
+
// route — ia tak berarti apa-apa di repoDir dan diam-diam mengabaikannya menyesatkan.
|
|
7242
|
+
worktree: external_exports.boolean().optional(),
|
|
7243
|
+
branchFrom: external_exports.string().min(1).max(255).optional()
|
|
7238
7244
|
}),
|
|
7239
7245
|
// SPEC-252 · ADR-0061 — model & effort per SESI: override opsional saat Start; kosong → global.
|
|
7240
7246
|
// SPEC-332 · ADR-0073 — mode goal per SESI: `goal` undefined → ikut Setting.goal.enabled,
|
|
@@ -11655,6 +11661,8 @@ var init_sessions = __esm({
|
|
|
11655
11661
|
} })
|
|
11656
11662
|
},
|
|
11657
11663
|
prdPath: str("flow `breakdown`: jalur PRD yang dipecah. WAJIB untuk alur itu."),
|
|
11664
|
+
worktree: bool("Terminal agen biasa (hanya `project`, tanpa `flow`/`shell`): true = lahir di worktree terpisah pada branch baru `term/<id>`, bukan langsung di repo project. Kosong = di repo project."),
|
|
11665
|
+
branchFrom: str("Bersama `worktree: true`: branch/ref asal worktree (lokal atau origin). Kosong = HEAD repo."),
|
|
11658
11666
|
force: bool("Lewati gerbang dependency. Pakai HANYA sesudah melihat daftar pemblokirnya.")
|
|
11659
11667
|
},
|
|
11660
11668
|
allOf: [
|
|
@@ -11684,7 +11692,8 @@ var init_sessions = __esm({
|
|
|
11684
11692
|
if (flow2 === "breakdown") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2, prdPath: String(a.prdPath) } };
|
|
11685
11693
|
if (flow2 === "reverse" || flow2 === "scaffold") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2 } };
|
|
11686
11694
|
const body = { project };
|
|
11687
|
-
for (const k of ["agent", "model", "effort"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
|
|
11695
|
+
for (const k of ["agent", "model", "effort", "branchFrom"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
|
|
11696
|
+
if (typeof a.worktree === "boolean") body.worktree = a.worktree;
|
|
11688
11697
|
return { method: "POST", path: "/terminal/sessions", body };
|
|
11689
11698
|
},
|
|
11690
11699
|
shape: (raw) => raw
|
package/dist/server.js
CHANGED
|
@@ -8115,7 +8115,13 @@ var init_dto = __esm({
|
|
|
8115
8115
|
agent: zAgent.optional(),
|
|
8116
8116
|
model: external_exports.string().optional(),
|
|
8117
8117
|
effort: external_exports.string().optional(),
|
|
8118
|
-
force: external_exports.boolean().optional()
|
|
8118
|
+
force: external_exports.boolean().optional(),
|
|
8119
|
+
// ADR-0232 · opsional: `worktree:true` → sesi lahir di `.worktrees/<id>` pada branch baru
|
|
8120
|
+
// `term/<id>` dari `branchFrom` (kosong → HEAD repo), alih-alih langsung di repoDir. Tanpa
|
|
8121
|
+
// keduanya body-nya byte-identik dengan sebelumnya. `branchFrom` tanpa `worktree` ditolak di
|
|
8122
|
+
// route — ia tak berarti apa-apa di repoDir dan diam-diam mengabaikannya menyesatkan.
|
|
8123
|
+
worktree: external_exports.boolean().optional(),
|
|
8124
|
+
branchFrom: external_exports.string().min(1).max(255).optional()
|
|
8119
8125
|
}),
|
|
8120
8126
|
// SPEC-252 · ADR-0061 — model & effort per SESI: override opsional saat Start; kosong → global.
|
|
8121
8127
|
// SPEC-332 · ADR-0073 — mode goal per SESI: `goal` undefined → ikut Setting.goal.enabled,
|
|
@@ -13238,6 +13244,8 @@ var init_sessions = __esm({
|
|
|
13238
13244
|
} })
|
|
13239
13245
|
},
|
|
13240
13246
|
prdPath: str("flow `breakdown`: jalur PRD yang dipecah. WAJIB untuk alur itu."),
|
|
13247
|
+
worktree: bool("Terminal agen biasa (hanya `project`, tanpa `flow`/`shell`): true = lahir di worktree terpisah pada branch baru `term/<id>`, bukan langsung di repo project. Kosong = di repo project."),
|
|
13248
|
+
branchFrom: str("Bersama `worktree: true`: branch/ref asal worktree (lokal atau origin). Kosong = HEAD repo."),
|
|
13241
13249
|
force: bool("Lewati gerbang dependency. Pakai HANYA sesudah melihat daftar pemblokirnya.")
|
|
13242
13250
|
},
|
|
13243
13251
|
allOf: [
|
|
@@ -13267,7 +13275,8 @@ var init_sessions = __esm({
|
|
|
13267
13275
|
if (flow2 === "breakdown") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2, prdPath: String(a.prdPath) } };
|
|
13268
13276
|
if (flow2 === "reverse" || flow2 === "scaffold") return { method: "POST", path: "/terminal/sessions", body: { project, flow: flow2 } };
|
|
13269
13277
|
const body = { project };
|
|
13270
|
-
for (const k of ["agent", "model", "effort"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
|
|
13278
|
+
for (const k of ["agent", "model", "effort", "branchFrom"]) if (s(a[k]) !== void 0) body[k] = s(a[k]);
|
|
13279
|
+
if (typeof a.worktree === "boolean") body.worktree = a.worktree;
|
|
13271
13280
|
return { method: "POST", path: "/terminal/sessions", body };
|
|
13272
13281
|
},
|
|
13273
13282
|
shape: (raw) => raw
|
|
@@ -78287,6 +78296,8 @@ init_src2();
|
|
|
78287
78296
|
init_session_phases();
|
|
78288
78297
|
init_spec_review2();
|
|
78289
78298
|
import { existsSync as existsSync18 } from "node:fs";
|
|
78299
|
+
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
78300
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
78290
78301
|
init_integrate();
|
|
78291
78302
|
init_settings3();
|
|
78292
78303
|
init_codex_trust();
|
|
@@ -79647,6 +79658,26 @@ async function terminal_default(app3, opts2) {
|
|
|
79647
79658
|
}
|
|
79648
79659
|
const { agent, model, effort: effort2 } = await terminalAgentDefaults(parsed.data);
|
|
79649
79660
|
if (agent === "codex") ensureCodexTrust(repoDir);
|
|
79661
|
+
if (parsed.data.worktree) {
|
|
79662
|
+
const id2 = `term-${randomUUID13().slice(0, 8)}`;
|
|
79663
|
+
const branch = `term/${id2.slice("term-".length)}`;
|
|
79664
|
+
const from = parsed.data.branchFrom ?? "HEAD";
|
|
79665
|
+
const result = await withSessionAdmission({ id: id2, exempt: false, force: parsed.data.force }, async () => {
|
|
79666
|
+
const wt = `${repoDir}/.worktrees/${id2}`;
|
|
79667
|
+
try {
|
|
79668
|
+
realGit.addWorktree(repoDir, wt, from);
|
|
79669
|
+
execFileSync9("git", ["switch", "-q", "-c", branch], { cwd: wt, stdio: "pipe" });
|
|
79670
|
+
} catch (e) {
|
|
79671
|
+
if (ownsWorktree(repoDir, wt)) realGit.removeWorktree(repoDir, wt);
|
|
79672
|
+
return { code: 422, body: { error: `gagal membuat worktree dari "${from}": ${e.message}` } };
|
|
79673
|
+
}
|
|
79674
|
+
const s3 = createSession(project.id, wt, { id: id2, agent, model, effort: effort2, branch });
|
|
79675
|
+
return { code: 201, body: { id: s3.id } };
|
|
79676
|
+
}, (pane) => ({ code: 201, body: { id: pane.id } }));
|
|
79677
|
+
return reply.code(result.code).send(result.body);
|
|
79678
|
+
}
|
|
79679
|
+
if (parsed.data.branchFrom)
|
|
79680
|
+
return reply.code(400).send({ error: "branchFrom hanya berlaku bersama worktree:true" });
|
|
79650
79681
|
const s2 = await createOperatorSession(
|
|
79651
79682
|
project.id,
|
|
79652
79683
|
repoDir,
|
|
@@ -80686,7 +80717,7 @@ async function listVpsWithScore() {
|
|
|
80686
80717
|
// src/services/vps-key.ts
|
|
80687
80718
|
init_src2();
|
|
80688
80719
|
init_config2();
|
|
80689
|
-
import { execFileSync as
|
|
80720
|
+
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
80690
80721
|
import { chmodSync as chmodSync9, copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync18, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "node:fs";
|
|
80691
80722
|
import { homedir as homedir11 } from "node:os";
|
|
80692
80723
|
import { join as join44 } from "node:path";
|
|
@@ -80712,7 +80743,7 @@ function ensureHanomanKey() {
|
|
|
80712
80743
|
if (!existsSync21(privPath)) adoptLegacyKey(dir2);
|
|
80713
80744
|
if (!existsSync21(privPath)) {
|
|
80714
80745
|
mkdirSync18(dir2, { recursive: true, mode: 448 });
|
|
80715
|
-
|
|
80746
|
+
execFileSync10(
|
|
80716
80747
|
"ssh-keygen",
|
|
80717
80748
|
["-t", "ed25519", "-N", "", "-C", "hanoman", "-f", privPath],
|
|
80718
80749
|
{ stdio: ["ignore", "ignore", "pipe"] }
|
|
@@ -81114,7 +81145,7 @@ async function antigravity(app3) {
|
|
|
81114
81145
|
// src/services/model-catalog.ts
|
|
81115
81146
|
init_src2();
|
|
81116
81147
|
init_src();
|
|
81117
|
-
import { randomUUID as
|
|
81148
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
81118
81149
|
import { readFile as readFile8, writeFile as writeFile6, rename as rename5, mkdir as mkdir9, rm as rm9 } from "node:fs/promises";
|
|
81119
81150
|
import { dirname as dirname18, join as join46 } from "node:path";
|
|
81120
81151
|
|
|
@@ -81425,7 +81456,7 @@ function createModelCatalogService(deps) {
|
|
|
81425
81456
|
async function writeModelCatalogCache(file, catalog, current = () => true) {
|
|
81426
81457
|
const sanitized = parseCachedCatalog(catalog);
|
|
81427
81458
|
await mkdir9(dirname18(file), { recursive: true });
|
|
81428
|
-
const temp = `${file}.${process.pid}.${
|
|
81459
|
+
const temp = `${file}.${process.pid}.${randomUUID14()}.tmp`;
|
|
81429
81460
|
try {
|
|
81430
81461
|
await writeFile6(temp, JSON.stringify(sanitized), { mode: 384, flag: "wx" });
|
|
81431
81462
|
if (current()) await rename5(temp, file);
|
|
@@ -87118,7 +87149,7 @@ init_qa_attachment_transfer();
|
|
|
87118
87149
|
init_uploads();
|
|
87119
87150
|
init_ask_via2();
|
|
87120
87151
|
import { createHash as createHash21 } from "node:crypto";
|
|
87121
|
-
import { execFileSync as
|
|
87152
|
+
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
87122
87153
|
import { join as join50 } from "node:path";
|
|
87123
87154
|
var QaSessionError = class extends Error {
|
|
87124
87155
|
constructor(code, message, needsBind = false) {
|
|
@@ -87153,7 +87184,7 @@ async function startQaFindingSession(d, fid) {
|
|
|
87153
87184
|
if (!reused) {
|
|
87154
87185
|
const base3 = realGit.revParse(repoDir, branch) ? branch : "HEAD";
|
|
87155
87186
|
realGit.addWorktree(repoDir, wt, base3);
|
|
87156
|
-
|
|
87187
|
+
execFileSync11("git", ["checkout", "-B", branch], { cwd: wt, encoding: "utf8" });
|
|
87157
87188
|
}
|
|
87158
87189
|
} catch (e) {
|
|
87159
87190
|
throw new QaSessionError(422, `Gagal membuat worktree QA: ${e.message}`);
|
|
@@ -89759,7 +89790,7 @@ init_event_log();
|
|
|
89759
89790
|
|
|
89760
89791
|
// src/services/remote-access-request.ts
|
|
89761
89792
|
init_src();
|
|
89762
|
-
import { randomUUID as
|
|
89793
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
89763
89794
|
var REQUEST_TIER_LABEL = { lihat: "Lihat", kerja: "Kerja", tulis: "Tulis" };
|
|
89764
89795
|
var entries3 = [];
|
|
89765
89796
|
var accepted = [];
|
|
@@ -89783,7 +89814,7 @@ function createAccessRequest(input, now = Date.now()) {
|
|
|
89783
89814
|
return { ok: false, reason: "rate-limited", retryAfterMs: accepted[0] + ACCESS_REQUEST_WINDOW_MS - now };
|
|
89784
89815
|
accepted.push(now);
|
|
89785
89816
|
const entry2 = {
|
|
89786
|
-
id:
|
|
89817
|
+
id: randomUUID15(),
|
|
89787
89818
|
tier: input.tier,
|
|
89788
89819
|
state: "pending",
|
|
89789
89820
|
requestedAt: now,
|
|
@@ -90971,7 +91002,7 @@ init_tap();
|
|
|
90971
91002
|
init_src();
|
|
90972
91003
|
init_db();
|
|
90973
91004
|
init_actor();
|
|
90974
|
-
import { randomUUID as
|
|
91005
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
90975
91006
|
function skipped(def2, row) {
|
|
90976
91007
|
if (!def2.skipWhen || !row) return false;
|
|
90977
91008
|
return row[def2.skipWhen.field] === def2.skipWhen.equals;
|
|
@@ -91037,7 +91068,7 @@ async function emitWebhook(i) {
|
|
|
91037
91068
|
const targets = matchingEndpoints(type, projectId);
|
|
91038
91069
|
if (!targets.length) return;
|
|
91039
91070
|
const name2 = projectId ? (await prisma.project.findUnique({ where: { id: projectId }, select: { name: true } }))?.name ?? null : null;
|
|
91040
|
-
const env = buildEnvelope(i, name2, (/* @__PURE__ */ new Date()).toISOString(), `evt_${
|
|
91071
|
+
const env = buildEnvelope(i, name2, (/* @__PURE__ */ new Date()).toISOString(), `evt_${randomUUID16().replace(/-/g, "")}`);
|
|
91041
91072
|
if (!env) return;
|
|
91042
91073
|
await enqueueEnvelope(env, targets);
|
|
91043
91074
|
} catch (e) {
|
|
@@ -753,3 +753,7 @@ boundary langsung membuang cache dan hasil in-flight lama. Probe hanya `--versio
|
|
|
753
753
|
10 detik dan 16 KiB per stream; sandbox aktif/hardening tidak mem-probe host. Kegagalan
|
|
754
754
|
observasi tidak memblokir sesi host. Tool tidak memasang CLI atau mengubah konfigurasi dan
|
|
755
755
|
endpoint/tool versi Codex tidak berubah.
|
|
756
|
+
|
|
757
|
+
ADR-0232: `hanoman_session_create` untuk terminal agen biasa (`project` tanpa `flow`/`shell`) menerima
|
|
758
|
+
`worktree: true` dan `branchFrom` — sesi lahir di worktree `.worktrees/term-<id>` pada branch baru
|
|
759
|
+
`term/<id>` dari branch pilihan. Tetap mode danger dengan capability `sessions:spawn`; tanpa tool baru.
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e,u as be,I as C,l as I,S as se,F as te}from"./index-
|
|
1
|
+
import{j as e,u as be,I as C,l as I,S as se,F as te}from"./index-CbX7iwxN.js";import{R as d}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function ye({height:s,color:a,rod:l}){return e.jsxs("svg",{viewBox:"0 0 64 128",width:s*64/128,height:s,"aria-hidden":"true",focusable:"false",children:[e.jsx("path",{d:"M31.2 74 L30.2 127 L33.8 127 L32.8 74 Z",fill:l}),e.jsx("path",{d:"M51 79 L50.2 122 L53 122 L52.4 79 Z",fill:l}),e.jsx("path",{d:`M32 73
|
|
2
2
|
C 24 76, 19 88, 17.5 103 C 17 106, 20 107, 24 106.4
|
|
3
3
|
C 28 106, 30 104, 32 104 C 34 104, 36 106, 40 106.4 C 44 107, 47 106, 46.5 103
|
|
4
4
|
C 45 88, 40 76, 32 73 Z`,fill:a}),e.jsx("path",{d:"M32 74 C 29.5 66, 29.5 60, 31 53 L 37 53 C 38.5 60, 37.5 67, 34.5 74 Z",fill:a}),e.jsx("path",{d:`M31 53
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e,M as r,aP as d,aR as a,m as x}from"./index-
|
|
1
|
+
import{j as e,M as r,aP as d,aR as a,m as x}from"./index-CbX7iwxN.js";import"./react-DfGhg7ZW.js";function f({path:i,text:o,eyebrow:n,download:t,onClose:s}){const l=i.slice(i.lastIndexOf("/")+1)||i;return e.jsx(r,{open:!0,title:l,eyebrow:n??i,icon:"book-open",onClose:s,width:980,fillHeight:!0,children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[t&&e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",paddingBottom:6,borderBottom:"1px solid var(--border-hair)",marginBottom:8},children:e.jsx(d,{href:t})}),e.jsx("div",{"data-testid":"doc-preview-scroll",style:{flex:"1 1 0",minHeight:0,overflow:"auto",padding:"0 4px 8px"},children:o?e.jsx(a,{text:o,name:i}):e.jsx(x,{kind:"empty",icon:"file-text",title:"Berkas kosong",hint:i})})]})})}export{f as D};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{q as Ne,d as De,h as S,j as e,m as w,I as N,U as Se,Y as Ce,B as O,f as Ke,n as U,O as Le,aP as Me,aR as te,D as Pe,aU as $e,i as ie}from"./index-BeFSh2Ba.js";import{R as o}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function de(n){let t={...n,kids:n.kids.map(de)};for(;!t.cat&&t.kids.length===1;){const i=t.kids[0];t={...i,label:t.label+"/"+i.label}}return t}function re(n){const t={path:"",kids:[]};for(const i of n){if(i.cat==="."){t.kids.push({path:".",label:".",cat:i,kids:[]});continue}let l=t;for(const u of i.cat.split("/")){const k=l.path?l.path+"/"+u:u;let m=l.kids.find(s=>s.path===k);m||(m={path:k,label:u,kids:[]},l.kids.push(m)),l=m}l.cat=i}return t.kids.map(de)}function le(n){const t=n.find(i=>i.scored&&i.linked)??n.find(i=>i.scored)??n[0];return t&&t.files[0]?`${t.cat}/${t.files[0]}`:""}function oe(n){return/(^|\/)adr(s)?(\/|$)/i.test(n)?"ADR":/(^|\/)prd(s)?(\/|$)/i.test(n)?"PRD":/(^|\/)spec(s|ification)?(\/|$)/i.test(n)?"Spec":"Lainnya"}const ze=["PRD","Spec","ADR","Lainnya"],ue=n=>`dir:${n}`,Fe=(n,t)=>!!t&&t.startsWith(n.path+"/");function he({node:n,depth:t,ctx:i}){var h,p,y;const l=Fe(n,i.selected),[u,k]=o.useState(l);o.useEffect(()=>{l&&k(!0)},[l]);const m=((h=n.cat)==null?void 0:h.scored)??!0,s=((p=n.cat)==null?void 0:p.linked)??!0,v=ue(n.path),b=()=>k(d=>!d),c=d=>{d.key==="Enter"||d.key===" "?(d.preventDefault(),b()):d.key==="ArrowRight"&&!u?(d.preventDefault(),k(!0)):d.key==="ArrowLeft"&&u&&(d.preventDefault(),k(!1))};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{role:"treeitem","aria-level":t+1,"aria-expanded":u,tabIndex:i.tabbable===v?0:-1,className:"hn-docs-node hn-docs-node-dir",style:{paddingLeft:6+t*12},onClick:b,onKeyDown:c,onFocus:()=>i.setFocusKey(v),children:[e.jsx(N,{name:u?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(N,{name:"folder",size:15,color:m?s?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{className:"hn-docs-dir-label",children:[n.label,"/"]}),n.cat&&m&&(n.cat.linked?e.jsx(N,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(N,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),u&&e.jsxs("div",{role:"group",className:"hn-docs-group",children:[n.kids.map(d=>e.jsx(he,{node:d,depth:t+1,ctx:i},d.path)),(y=n.cat)==null?void 0:y.files.map(d=>{const f=n.path+"/"+d,j=f===i.selected;return e.jsxs("div",{role:"treeitem","aria-level":t+2,"aria-selected":j,"aria-current":j?"true":void 0,tabIndex:i.tabbable===f?0:-1,className:`hn-docs-node hn-docs-node-file${j?" is-selected":""}`,style:{paddingLeft:18+t*12},onClick:()=>i.onSelect(f),onFocus:()=>i.setFocusKey(f),onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&(g.preventDefault(),i.onSelect(f))},children:[e.jsx(N,{name:"file-text",size:13,color:j?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{className:`hn-docs-file-label${!m||s?"":" is-unlinked"}`,children:d})]},d)})]})]})}function ce({label:n,nodes:t,selected:i,onSelect:l}){const[u,k]=o.useState(null),m=t[0]?ue(t[0].path):"",v={selected:i,onSelect:l,tabbable:u??(i||m),setFocusKey:c=>k(c)},b=c=>{if(c.key!=="ArrowDown"&&c.key!=="ArrowUp")return;const h=Array.from(c.currentTarget.querySelectorAll('[role="treeitem"]')),p=h.indexOf(document.activeElement);if(p<0)return;c.preventDefault();const y=h[Math.min(h.length-1,Math.max(0,p+(c.key==="ArrowDown"?1:-1)))];y==null||y.focus()};return e.jsx("div",{role:"tree","aria-label":n,className:"hn-docs-tree",onKeyDown:b,children:t.map(c=>e.jsx(he,{node:c,depth:0,ctx:v},c.path))})}function Ie({projectId:n,projectName:t,docStatus:i}){const[l,u]=o.useState([]),[k,m]=o.useState(0),[s,v]=Ne($e("docs",n),"selected","",Pe),[b,c]=o.useState({}),[h,p]=o.useState("preview"),[y,d]=o.useState("tree"),[f,j]=o.useState(""),[g,q]=o.useState(!1),[L,W]=o.useState(!1),[G,C]=o.useState(""),[P,J]=o.useState(""),[D,$]=o.useState("all"),{confirm:Q,dialog:me}=De(),[z,K]=o.useState("loading"),[pe,ke]=o.useState(0);o.useEffect(()=>{let a=!0;return K("loading"),S.getDocs(n).then(r=>{if(!a)return;const x=r.tree;u(x),m(r.coverage),c({}),p("preview"),K("ready"),C(""),J(""),$("all"),v(le(x))}).catch(()=>{a&&(u([]),v(""),K("error"))}),()=>{a=!1}},[n,pe]),o.useEffect(()=>{if(!s||s in b)return;let a=!0;return S.getDoc(n,s).then(r=>{a&&c(x=>({...x,[s]:r.content}))}).catch(()=>{a&&c(r=>({...r,[s]:null}))}),()=>{a=!1}},[s,n,b]);const F=!!s&&!(s in b),A=s?b[s]===null:!1,fe=()=>c(a=>{const r={...a};return delete r[s],r}),V=a=>D==="all"||oe(a.cat)===D,xe=re(l.filter(a=>a.scored&&V(a))),Y=re(l.filter(a=>!a.scored&&V(a))),B=b[s]??"",be=s.includes("/")?s.slice(0,s.lastIndexOf("/")):".",T=l.find(a=>a.cat===be),_=s,E=h==="edit"&&f!==B,I=o.useMemo(()=>l.flatMap(a=>a.files.map(r=>({key:`${a.cat}/${r}`,scored:a.scored,linked:a.linked,kind:oe(a.cat)}))),[l]),R=P.trim().toLowerCase(),X=R?I.filter(a=>(D==="all"||a.kind===D)&&a.key.toLowerCase().includes(R)):[],ve=o.useMemo(()=>{const a={PRD:0,Spec:0,ADR:0,Lainnya:0};for(const r of I)a[r.kind]+=1;return a},[I]),ye=i==="broken"?"broken":i==="drift"?"drift":"ok";function Z(a){if(!E){p("preview"),a();return}Q({title:"Buang perubahan?",eyebrow:s,message:"Isi dokumen yang kamu ubah belum disimpan.",impact:["Perubahan di editor hilang dan tak bisa dikembalikan dari dashboard."],confirmLabel:"Buang perubahan",cancelLabel:"Lanjut mengedit",tone:"danger",icon:"trash-2"}).then(r=>{r&&(p("preview"),a())})}function ge(){C(""),j(B),p("edit")}const ee=()=>Z(()=>{});async function ae(){if(!(L||!s)){W(!0),C("");try{await S.putDoc(n,s,f),c(a=>({...a,[s]:f})),p("preview")}catch(a){C(ie("menyimpan dokumen",a))}finally{W(!1)}}}function H(a){Z(()=>{v(a),p("preview"),d("viewer")})}async function se(){const a=await S.getDocs(n),r=a.tree;u(r),m(a.coverage),r.some(x=>x.files.some(M=>`${x.cat}/${M}`===s))||v(le(r))}async function ne(){if(!g){q(!0);try{await se()}catch{K("error")}finally{q(!1)}}}async function je(){if(!s)return;const a=s;let r=!1;try{r=await Q({title:`Hapus ${a}?`,eyebrow:"Source of Truth",message:"Dokumen ini adalah Source of Truth project. Berkas aslinya di disk ikut dihapus.",impact:["Berkas di disk dihapus dan tak bisa dikembalikan dari dashboard.","Kategori indeks dihitung ulang setelah penghapusan."],confirmLabel:"Hapus dokumen",tone:"danger",icon:"trash-2",run:()=>S.deleteDoc(n,a)})}catch(x){C(ie("menghapus dokumen",x));return}if(r){c(x=>{const M={...x};return delete M[a],M});try{await se()}catch{K("error")}}}const we=z==="loading"?e.jsx(w,{kind:"loading",compact:!0,title:"Memuat indeks…"}):z==="error"?e.jsx(w,{kind:"error",compact:!0,title:"Gagal memuat indeks dokumen",hint:t,action:()=>ke(a=>a+1)}):l.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada dokumen",hint:"Belum ada Markdown di repo ini.",action:ne,actionLabel:"Muat ulang",actionIcon:"radar"}):R?X.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"search",title:"Tak ada berkas cocok",hint:`Tak ada yang cocok dengan “${P.trim()}”.`}):e.jsx("div",{role:"list","aria-label":"Hasil pencarian berkas",className:"hn-docs-results",children:X.map(a=>e.jsxs("button",{type:"button","aria-current":a.key===s?"true":void 0,onClick:()=>H(a.key),className:`hn-docs-result${a.key===s?" is-selected":""}`,children:[e.jsx(N,{name:"file-text",size:13,color:"var(--text-subtle)"}),e.jsx("span",{className:"hn-prj-mono",children:a.key}),e.jsx("span",{className:"hn-docs-result-kind",children:a.kind})]},a.key))}):e.jsxs(e.Fragment,{children:[e.jsx(ce,{label:"Berkas dokumen",nodes:xe,selected:s,onSelect:H}),Y.length>0&&e.jsxs("div",{className:"hn-docs-unscored",children:[e.jsx("div",{className:"hn-eyebrow hn-docs-unscored-label",children:"Lainnya (tidak dinilai)"}),e.jsx(ce,{label:"Dokumen tidak dinilai",nodes:Y,selected:s,onSelect:H})]})]});return e.jsxs(e.Fragment,{children:[e.jsx(Se,{ariaLabel:"Panel Dokumen",active:y,onActiveChange:a=>d(a),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Indeks",className:"hn-panel-flex",content:e.jsxs("aside",{"aria-label":"Indeks dokumen",className:"hn-docs-index",children:[e.jsxs("div",{className:"hn-docs-index-head",children:[e.jsxs("span",{className:"hn-eyebrow",children:["dokumen · ",t]}),e.jsxs("div",{className:"hn-docs-index-actions",children:[e.jsx(Ce,{status:ye,size:"sm"}),e.jsx(O,{size:"sm",variant:"ghost",leftIcon:g?"loader":"radar",onClick:ne,disabled:g,children:g?"Memuat…":"Muat ulang"})]})]}),z==="ready"&&l.length>0&&e.jsxs("div",{className:"hn-docs-index-tools",children:[e.jsx(Ke,{size:"sm","aria-label":"Cari berkas dokumen",leftIcon:"search",value:P,placeholder:"mis. product/prd",onChange:a=>J(a.target.value),className:"hn-prj-full"}),e.jsxs("div",{role:"group","aria-label":"Kategori dokumen",className:"hn-prj-chips",children:[e.jsx("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D==="all",onClick:()=>$("all"),children:"Semua"}),ze.map(a=>e.jsxs("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D===a,onClick:()=>$(a),children:[a,e.jsx("span",{className:"hn-prj-chip-count",children:ve[a]})]},a))]}),e.jsxs("span",{className:"hn-docs-cov",title:"Persentase kategori yang terindeks",children:["Cakupan ",Math.round(k),"%"]})]}),e.jsx("div",{className:"hn-docs-tree-scroll",children:we})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs("section",{"aria-label":"Isi dokumen",className:"hn-docs-viewer",style:{display:"flex",flexDirection:"column",minHeight:0},children:[e.jsxs("div",{className:"hn-docs-viewer-head",children:[e.jsx(N,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{className:"hn-prj-mono hn-docs-path",children:_}),T&&T.scored&&(T.linked?e.jsx(U,{tone:"ok",size:"sm",icon:"link",children:"terindeks"}):e.jsx(U,{tone:"err",size:"sm",icon:"unlink",children:"tak tertaut"})),e.jsx("span",{className:"hn-grow"}),e.jsxs("div",{role:"group","aria-label":"Mode dokumen",className:"hn-prj-seg",children:[e.jsx("button",{type:"button","aria-pressed":h==="preview",className:"hn-touch-target",onClick:()=>{h==="edit"&&ee()},children:"Baca"}),e.jsx("button",{type:"button","aria-pressed":h==="edit",className:"hn-touch-target",onClick:()=>{h!=="edit"&&ge()},disabled:!s||F||A,children:"Edit"})]}),h==="preview"&&e.jsx(Le,{label:"Aksi untuk dokumen",icon:"ellipsis",items:[{key:"delete",label:"Hapus dokumen…",icon:"trash-2",tone:"danger",disabled:!s,onSelect:()=>{je()}}],children:e.jsx(Me,{href:a=>S.docDownloadUrl(n,s,a),disabled:!s||F||A})})]}),h==="edit"&&e.jsxs("div",{role:"region","aria-label":"Simpan perubahan",className:"hn-docs-savebar",children:[E?e.jsx(U,{tone:"warn",size:"sm",children:"belum disimpan"}):e.jsx("span",{className:"hn-prj-hint",children:"Tak ada perubahan"}),e.jsx("span",{className:"hn-grow"}),e.jsx(O,{size:"sm",variant:"ghost",onClick:ee,disabled:L,children:"Batal"}),e.jsx(O,{size:"sm",leftIcon:"check",onClick:()=>void ae(),loading:L,disabled:L||!E,children:"Simpan"})]}),G&&e.jsx("div",{role:"alert",className:"hn-docs-error",children:G}),h==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",className:"hn-docs-body",style:{flex:"1 1 auto",minHeight:0,overflow:"auto"},children:s?F?e.jsx(w,{kind:"loading",title:"Memuat dokumen…",hint:s}):A?e.jsx(w,{kind:"error",title:"Gagal memuat dokumen",hint:s,action:fe}):e.jsx("div",{className:"hn-docs-read",children:e.jsx(te,{text:B,name:s})}):e.jsx(w,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari indeks di kiri."})}):e.jsxs("div",{className:"hn-docs-edit",children:[e.jsxs("div",{className:"hn-docs-edit-pane",children:[e.jsx("div",{className:"hn-docs-edit-label",children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{"aria-label":`Isi ${_}`,value:f,spellCheck:!1,onChange:a=>j(a.target.value),onKeyDown:a=>{(a.metaKey||a.ctrlKey)&&a.key.toLowerCase()==="s"&&(a.preventDefault(),ae())},placeholder:`# Judul dokumen
|
|
1
|
+
import{q as Ne,d as De,h as S,j as e,m as w,I as N,U as Se,Y as Ce,B as O,f as Ke,n as U,O as Le,aP as Me,aR as te,D as Pe,aU as $e,i as ie}from"./index-CbX7iwxN.js";import{R as o}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function de(n){let t={...n,kids:n.kids.map(de)};for(;!t.cat&&t.kids.length===1;){const i=t.kids[0];t={...i,label:t.label+"/"+i.label}}return t}function re(n){const t={path:"",kids:[]};for(const i of n){if(i.cat==="."){t.kids.push({path:".",label:".",cat:i,kids:[]});continue}let l=t;for(const u of i.cat.split("/")){const k=l.path?l.path+"/"+u:u;let m=l.kids.find(s=>s.path===k);m||(m={path:k,label:u,kids:[]},l.kids.push(m)),l=m}l.cat=i}return t.kids.map(de)}function le(n){const t=n.find(i=>i.scored&&i.linked)??n.find(i=>i.scored)??n[0];return t&&t.files[0]?`${t.cat}/${t.files[0]}`:""}function oe(n){return/(^|\/)adr(s)?(\/|$)/i.test(n)?"ADR":/(^|\/)prd(s)?(\/|$)/i.test(n)?"PRD":/(^|\/)spec(s|ification)?(\/|$)/i.test(n)?"Spec":"Lainnya"}const ze=["PRD","Spec","ADR","Lainnya"],ue=n=>`dir:${n}`,Fe=(n,t)=>!!t&&t.startsWith(n.path+"/");function he({node:n,depth:t,ctx:i}){var h,p,y;const l=Fe(n,i.selected),[u,k]=o.useState(l);o.useEffect(()=>{l&&k(!0)},[l]);const m=((h=n.cat)==null?void 0:h.scored)??!0,s=((p=n.cat)==null?void 0:p.linked)??!0,v=ue(n.path),b=()=>k(d=>!d),c=d=>{d.key==="Enter"||d.key===" "?(d.preventDefault(),b()):d.key==="ArrowRight"&&!u?(d.preventDefault(),k(!0)):d.key==="ArrowLeft"&&u&&(d.preventDefault(),k(!1))};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{role:"treeitem","aria-level":t+1,"aria-expanded":u,tabIndex:i.tabbable===v?0:-1,className:"hn-docs-node hn-docs-node-dir",style:{paddingLeft:6+t*12},onClick:b,onKeyDown:c,onFocus:()=>i.setFocusKey(v),children:[e.jsx(N,{name:u?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(N,{name:"folder",size:15,color:m?s?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{className:"hn-docs-dir-label",children:[n.label,"/"]}),n.cat&&m&&(n.cat.linked?e.jsx(N,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(N,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),u&&e.jsxs("div",{role:"group",className:"hn-docs-group",children:[n.kids.map(d=>e.jsx(he,{node:d,depth:t+1,ctx:i},d.path)),(y=n.cat)==null?void 0:y.files.map(d=>{const f=n.path+"/"+d,j=f===i.selected;return e.jsxs("div",{role:"treeitem","aria-level":t+2,"aria-selected":j,"aria-current":j?"true":void 0,tabIndex:i.tabbable===f?0:-1,className:`hn-docs-node hn-docs-node-file${j?" is-selected":""}`,style:{paddingLeft:18+t*12},onClick:()=>i.onSelect(f),onFocus:()=>i.setFocusKey(f),onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&(g.preventDefault(),i.onSelect(f))},children:[e.jsx(N,{name:"file-text",size:13,color:j?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{className:`hn-docs-file-label${!m||s?"":" is-unlinked"}`,children:d})]},d)})]})]})}function ce({label:n,nodes:t,selected:i,onSelect:l}){const[u,k]=o.useState(null),m=t[0]?ue(t[0].path):"",v={selected:i,onSelect:l,tabbable:u??(i||m),setFocusKey:c=>k(c)},b=c=>{if(c.key!=="ArrowDown"&&c.key!=="ArrowUp")return;const h=Array.from(c.currentTarget.querySelectorAll('[role="treeitem"]')),p=h.indexOf(document.activeElement);if(p<0)return;c.preventDefault();const y=h[Math.min(h.length-1,Math.max(0,p+(c.key==="ArrowDown"?1:-1)))];y==null||y.focus()};return e.jsx("div",{role:"tree","aria-label":n,className:"hn-docs-tree",onKeyDown:b,children:t.map(c=>e.jsx(he,{node:c,depth:0,ctx:v},c.path))})}function Ie({projectId:n,projectName:t,docStatus:i}){const[l,u]=o.useState([]),[k,m]=o.useState(0),[s,v]=Ne($e("docs",n),"selected","",Pe),[b,c]=o.useState({}),[h,p]=o.useState("preview"),[y,d]=o.useState("tree"),[f,j]=o.useState(""),[g,q]=o.useState(!1),[L,W]=o.useState(!1),[G,C]=o.useState(""),[P,J]=o.useState(""),[D,$]=o.useState("all"),{confirm:Q,dialog:me}=De(),[z,K]=o.useState("loading"),[pe,ke]=o.useState(0);o.useEffect(()=>{let a=!0;return K("loading"),S.getDocs(n).then(r=>{if(!a)return;const x=r.tree;u(x),m(r.coverage),c({}),p("preview"),K("ready"),C(""),J(""),$("all"),v(le(x))}).catch(()=>{a&&(u([]),v(""),K("error"))}),()=>{a=!1}},[n,pe]),o.useEffect(()=>{if(!s||s in b)return;let a=!0;return S.getDoc(n,s).then(r=>{a&&c(x=>({...x,[s]:r.content}))}).catch(()=>{a&&c(r=>({...r,[s]:null}))}),()=>{a=!1}},[s,n,b]);const F=!!s&&!(s in b),A=s?b[s]===null:!1,fe=()=>c(a=>{const r={...a};return delete r[s],r}),V=a=>D==="all"||oe(a.cat)===D,xe=re(l.filter(a=>a.scored&&V(a))),Y=re(l.filter(a=>!a.scored&&V(a))),B=b[s]??"",be=s.includes("/")?s.slice(0,s.lastIndexOf("/")):".",T=l.find(a=>a.cat===be),_=s,E=h==="edit"&&f!==B,I=o.useMemo(()=>l.flatMap(a=>a.files.map(r=>({key:`${a.cat}/${r}`,scored:a.scored,linked:a.linked,kind:oe(a.cat)}))),[l]),R=P.trim().toLowerCase(),X=R?I.filter(a=>(D==="all"||a.kind===D)&&a.key.toLowerCase().includes(R)):[],ve=o.useMemo(()=>{const a={PRD:0,Spec:0,ADR:0,Lainnya:0};for(const r of I)a[r.kind]+=1;return a},[I]),ye=i==="broken"?"broken":i==="drift"?"drift":"ok";function Z(a){if(!E){p("preview"),a();return}Q({title:"Buang perubahan?",eyebrow:s,message:"Isi dokumen yang kamu ubah belum disimpan.",impact:["Perubahan di editor hilang dan tak bisa dikembalikan dari dashboard."],confirmLabel:"Buang perubahan",cancelLabel:"Lanjut mengedit",tone:"danger",icon:"trash-2"}).then(r=>{r&&(p("preview"),a())})}function ge(){C(""),j(B),p("edit")}const ee=()=>Z(()=>{});async function ae(){if(!(L||!s)){W(!0),C("");try{await S.putDoc(n,s,f),c(a=>({...a,[s]:f})),p("preview")}catch(a){C(ie("menyimpan dokumen",a))}finally{W(!1)}}}function H(a){Z(()=>{v(a),p("preview"),d("viewer")})}async function se(){const a=await S.getDocs(n),r=a.tree;u(r),m(a.coverage),r.some(x=>x.files.some(M=>`${x.cat}/${M}`===s))||v(le(r))}async function ne(){if(!g){q(!0);try{await se()}catch{K("error")}finally{q(!1)}}}async function je(){if(!s)return;const a=s;let r=!1;try{r=await Q({title:`Hapus ${a}?`,eyebrow:"Source of Truth",message:"Dokumen ini adalah Source of Truth project. Berkas aslinya di disk ikut dihapus.",impact:["Berkas di disk dihapus dan tak bisa dikembalikan dari dashboard.","Kategori indeks dihitung ulang setelah penghapusan."],confirmLabel:"Hapus dokumen",tone:"danger",icon:"trash-2",run:()=>S.deleteDoc(n,a)})}catch(x){C(ie("menghapus dokumen",x));return}if(r){c(x=>{const M={...x};return delete M[a],M});try{await se()}catch{K("error")}}}const we=z==="loading"?e.jsx(w,{kind:"loading",compact:!0,title:"Memuat indeks…"}):z==="error"?e.jsx(w,{kind:"error",compact:!0,title:"Gagal memuat indeks dokumen",hint:t,action:()=>ke(a=>a+1)}):l.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada dokumen",hint:"Belum ada Markdown di repo ini.",action:ne,actionLabel:"Muat ulang",actionIcon:"radar"}):R?X.length===0?e.jsx(w,{kind:"empty",compact:!0,icon:"search",title:"Tak ada berkas cocok",hint:`Tak ada yang cocok dengan “${P.trim()}”.`}):e.jsx("div",{role:"list","aria-label":"Hasil pencarian berkas",className:"hn-docs-results",children:X.map(a=>e.jsxs("button",{type:"button","aria-current":a.key===s?"true":void 0,onClick:()=>H(a.key),className:`hn-docs-result${a.key===s?" is-selected":""}`,children:[e.jsx(N,{name:"file-text",size:13,color:"var(--text-subtle)"}),e.jsx("span",{className:"hn-prj-mono",children:a.key}),e.jsx("span",{className:"hn-docs-result-kind",children:a.kind})]},a.key))}):e.jsxs(e.Fragment,{children:[e.jsx(ce,{label:"Berkas dokumen",nodes:xe,selected:s,onSelect:H}),Y.length>0&&e.jsxs("div",{className:"hn-docs-unscored",children:[e.jsx("div",{className:"hn-eyebrow hn-docs-unscored-label",children:"Lainnya (tidak dinilai)"}),e.jsx(ce,{label:"Dokumen tidak dinilai",nodes:Y,selected:s,onSelect:H})]})]});return e.jsxs(e.Fragment,{children:[e.jsx(Se,{ariaLabel:"Panel Dokumen",active:y,onActiveChange:a=>d(a),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Indeks",className:"hn-panel-flex",content:e.jsxs("aside",{"aria-label":"Indeks dokumen",className:"hn-docs-index",children:[e.jsxs("div",{className:"hn-docs-index-head",children:[e.jsxs("span",{className:"hn-eyebrow",children:["dokumen · ",t]}),e.jsxs("div",{className:"hn-docs-index-actions",children:[e.jsx(Ce,{status:ye,size:"sm"}),e.jsx(O,{size:"sm",variant:"ghost",leftIcon:g?"loader":"radar",onClick:ne,disabled:g,children:g?"Memuat…":"Muat ulang"})]})]}),z==="ready"&&l.length>0&&e.jsxs("div",{className:"hn-docs-index-tools",children:[e.jsx(Ke,{size:"sm","aria-label":"Cari berkas dokumen",leftIcon:"search",value:P,placeholder:"mis. product/prd",onChange:a=>J(a.target.value),className:"hn-prj-full"}),e.jsxs("div",{role:"group","aria-label":"Kategori dokumen",className:"hn-prj-chips",children:[e.jsx("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D==="all",onClick:()=>$("all"),children:"Semua"}),ze.map(a=>e.jsxs("button",{type:"button",className:"hn-prj-chip hn-touch-target","aria-pressed":D===a,onClick:()=>$(a),children:[a,e.jsx("span",{className:"hn-prj-chip-count",children:ve[a]})]},a))]}),e.jsxs("span",{className:"hn-docs-cov",title:"Persentase kategori yang terindeks",children:["Cakupan ",Math.round(k),"%"]})]}),e.jsx("div",{className:"hn-docs-tree-scroll",children:we})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs("section",{"aria-label":"Isi dokumen",className:"hn-docs-viewer",style:{display:"flex",flexDirection:"column",minHeight:0},children:[e.jsxs("div",{className:"hn-docs-viewer-head",children:[e.jsx(N,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{className:"hn-prj-mono hn-docs-path",children:_}),T&&T.scored&&(T.linked?e.jsx(U,{tone:"ok",size:"sm",icon:"link",children:"terindeks"}):e.jsx(U,{tone:"err",size:"sm",icon:"unlink",children:"tak tertaut"})),e.jsx("span",{className:"hn-grow"}),e.jsxs("div",{role:"group","aria-label":"Mode dokumen",className:"hn-prj-seg",children:[e.jsx("button",{type:"button","aria-pressed":h==="preview",className:"hn-touch-target",onClick:()=>{h==="edit"&&ee()},children:"Baca"}),e.jsx("button",{type:"button","aria-pressed":h==="edit",className:"hn-touch-target",onClick:()=>{h!=="edit"&&ge()},disabled:!s||F||A,children:"Edit"})]}),h==="preview"&&e.jsx(Le,{label:"Aksi untuk dokumen",icon:"ellipsis",items:[{key:"delete",label:"Hapus dokumen…",icon:"trash-2",tone:"danger",disabled:!s,onSelect:()=>{je()}}],children:e.jsx(Me,{href:a=>S.docDownloadUrl(n,s,a),disabled:!s||F||A})})]}),h==="edit"&&e.jsxs("div",{role:"region","aria-label":"Simpan perubahan",className:"hn-docs-savebar",children:[E?e.jsx(U,{tone:"warn",size:"sm",children:"belum disimpan"}):e.jsx("span",{className:"hn-prj-hint",children:"Tak ada perubahan"}),e.jsx("span",{className:"hn-grow"}),e.jsx(O,{size:"sm",variant:"ghost",onClick:ee,disabled:L,children:"Batal"}),e.jsx(O,{size:"sm",leftIcon:"check",onClick:()=>void ae(),loading:L,disabled:L||!E,children:"Simpan"})]}),G&&e.jsx("div",{role:"alert",className:"hn-docs-error",children:G}),h==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",className:"hn-docs-body",style:{flex:"1 1 auto",minHeight:0,overflow:"auto"},children:s?F?e.jsx(w,{kind:"loading",title:"Memuat dokumen…",hint:s}):A?e.jsx(w,{kind:"error",title:"Gagal memuat dokumen",hint:s,action:fe}):e.jsx("div",{className:"hn-docs-read",children:e.jsx(te,{text:B,name:s})}):e.jsx(w,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari indeks di kiri."})}):e.jsxs("div",{className:"hn-docs-edit",children:[e.jsxs("div",{className:"hn-docs-edit-pane",children:[e.jsx("div",{className:"hn-docs-edit-label",children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{"aria-label":`Isi ${_}`,value:f,spellCheck:!1,onChange:a=>j(a.target.value),onKeyDown:a=>{(a.metaKey||a.ctrlKey)&&a.key.toLowerCase()==="s"&&(a.preventDefault(),ae())},placeholder:`# Judul dokumen
|
|
2
2
|
|
|
3
3
|
Paragraf pembuka…`,className:"hn-docs-textarea"})]}),e.jsxs("div",{className:"hn-docs-edit-pane",children:[e.jsx("div",{className:"hn-docs-edit-label",children:e.jsx("span",{className:"hn-eyebrow",children:"Pratinjau langsung"})}),e.jsx("div",{className:"hn-docs-preview",children:e.jsx(te,{text:f,name:s})})]})]})]})}]}),me]})}export{Ie as DocsWorkspace,re as buildTree,oe as docKind,le as firstDoc};
|