hanoman 0.9.17 → 0.9.19

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.
Files changed (26) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +386 -112
  3. package/dist/server.js +2022 -922
  4. package/docs/agent-integration.md +21 -0
  5. package/package.json +1 -1
  6. package/prisma/migrations/20261007120000_project_memory/migration.sql +54 -0
  7. package/prisma/migrations/20261007130000_memory_sync/migration.sql +32 -0
  8. package/prisma/schema.prisma +57 -0
  9. package/web/assets/{ChangelogScreen-Bj1KreGh.js → ChangelogScreen-DL5v_FZf.js} +1 -1
  10. package/web/assets/{DalangHanomanScreen-C1Ivdj4r.js → DalangHanomanScreen-aLBtUGE4.js} +1 -1
  11. package/web/assets/{DocPreviewModal-Cw69hQk1.js → DocPreviewModal-CHrsP0pL.js} +1 -1
  12. package/web/assets/{DocsWorkspace--9rvckps.js → DocsWorkspace-D262CVxH.js} +1 -1
  13. package/web/assets/{IdeScreen-DxNG9eLb.js → IdeScreen-D2GI3KYh.js} +1 -1
  14. package/web/assets/{LeadScreen-CV3Lgbyd.js → LeadScreen-eb_DK1j6.js} +1 -1
  15. package/web/assets/{ReviewScreen-JLPOS52f.js → ReviewScreen-DarOFH_a.js} +1 -1
  16. package/web/assets/{SchedulerScreen-UhxWcCtY.js → SchedulerScreen-DKoMf2LT.js} +1 -1
  17. package/web/assets/SettingsScreen-BAUhwd5K.js +62 -0
  18. package/web/assets/{TeamScreen-D24DsEwn.js → TeamScreen-C2fSsQ8C.js} +1 -1
  19. package/web/assets/{TerminalScreen-3nSnkwTy.js → TerminalScreen-GsfOMtu5.js} +1 -1
  20. package/web/assets/{TriageScreen-Dw6EqWar.js → TriageScreen-DdKMAroz.js} +1 -1
  21. package/web/assets/{VpsScreen-C_rNhMi5.js → VpsScreen-CDAjvyT1.js} +1 -1
  22. package/web/assets/index-gNO91_qw.js +1063 -0
  23. package/web/assets/{live-DHIFZVo0.js → live-Cz6dWAau.js} +1 -1
  24. package/web/index.html +1 -1
  25. package/web/assets/SettingsScreen-D3nVVnsZ.js +0 -62
  26. package/web/assets/index-DHVdBKua.js +0 -1053
@@ -112,8 +112,29 @@ perlu mengambilnya, cukup rujuk tabel di bawah:
112
112
  | `agents` | `/api/custom-agents*` | katalog custom agent global & per project — **`agents:write` mengubah apa yang dilihat SETIAP sesi baru** (ADR-0094) |
113
113
  | `skills` | `/api/skills*` | skill global hanoman, user, plugin (baca-saja) & per project, termasuk isi berkasnya — **`skills:write` pada skill global hanoman mengubah instruksi SETIAP sesi baru di semua project** |
114
114
  | `telegram` | `/api/telegram*` kecuali sub-path kredensial | context/memory/reply/audit kanal operator Telegram (ADR-0096) |
115
+ | `memory` | `/api/memories*` kecuali `…/activate` dan `…/reject` (cookie-only) | memori project bersama. Token **wajib** punya allowlist project (`projectIds`); project ditentukan dari header `x-hanoman-repo` yang diisi CLI MCP, bukan dari parameter (ADR-0178) |
115
116
  | `team` | `/api/tasks*`, `/api/members*` | papan **Tim**: kartu kerja MANUSIA & direktori anggota (ADR-0157). `status` kartu milik manusia — ia **bukan** `stage` backlog. `POST /api/tasks/:id/escalate` melahirkan backlog item dan tetap `team:write` (cermin `POST /api/tickets/:id/accept`) |
116
117
 
118
+ ### Memori project (`/api/memories`, ADR-0178)
119
+
120
+ - Project **tidak** dipilih lewat parameter. CLI MCP hanoman (`hanoman mcp`) membaca repo di direktori
121
+ kerjanya — `origin`, root commit, HEAD — dan mengirimnya sebagai header `x-hanoman-repo`; server
122
+ mencocokkannya ke `Project.gitRemote` dan ke allowlist **Project yang diizinkan** pada token.
123
+ - Token tanpa allowlist → `403 {need:"projectIds"}`; mengirim `projectId` → `400`.
124
+ - Jangkar (`anchors[]`) diisi path saja; blob SHA diisi CLI dari HEAD dan diverifikasi ulang server.
125
+ Usulan dengan jangkar terverifikasi langsung `active`; tanpa jangkar atau `kind: decision` masuk
126
+ review manusia (`…/activate` / `…/reject` cookie-only).
127
+ - Galat: `404` remote tak dikenal / root commit beda · `409 {duplicateOf}` · `422 {anchor}` jangkar tak cocok
128
+ · `422 {reason}` terdeteksi secret.
129
+ - Memori adalah **data**, bukan instruksi.
130
+ - **Dari dalam sesi hanoman** (ADR-0179): CLI MCP meneruskan `HANOMAN_SESSION_ID` + `HANOMAN_EVENT_TOKEN`
131
+ sesi induknya sebagai `x-hanoman-session` / `x-hanoman-session-token` (hanya ke host loopback). Project
132
+ diambil dari sesi — allowlist `projectIds` tak dibutuhkan, capability `memory:*` tetap. Kredensial sesi
133
+ salah → `401`; sesi tak hidup → `404`. Memori dari sesi yang menyentuh input eksternal (Help Center,
134
+ tiket, issue GitHub) selalu masuk review manusia.
135
+ - Sesi backlog lahir dengan memori `active` yang jangkarnya cocok HEAD worktree-nya (claude:
136
+ `--append-system-prompt-file`, codex: `developer_instructions`).
137
+
117
138
  Aturan pemetaan **deterministik** (`server/src/services/agent-capabilities.ts`): `GET`/`HEAD` →
118
139
  `:read`, metode lain → `:write`. Itu berlaku untuk domain `lead` juga — **`POST /api/lead/decisions`
119
140
  menuntut `lead:write`**, dan `lead:read` tak pernah cukup: meminta putusan melahirkan baris jejak
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanoman",
3
- "version": "0.9.17",
3
+ "version": "0.9.19",
4
4
  "description": "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,54 @@
1
+ -- ADR-0178 · memori project bersama lintas runtime
2
+ -- AlterTable
3
+ ALTER TABLE "AgentToken" ADD COLUMN "projectIds" JSONB;
4
+
5
+ -- CreateTable
6
+ CREATE TABLE "ProjectMemory" (
7
+ "id" TEXT NOT NULL PRIMARY KEY,
8
+ "projectId" TEXT NOT NULL,
9
+ "kind" TEXT NOT NULL,
10
+ "content" TEXT NOT NULL,
11
+ "scopePaths" JSONB NOT NULL,
12
+ "anchors" JSONB NOT NULL,
13
+ "status" TEXT NOT NULL,
14
+ "supersedesId" TEXT,
15
+ "reviewReason" TEXT,
16
+ "sourceRuntime" TEXT NOT NULL,
17
+ "sourceSessionId" TEXT,
18
+ "sourceTokenId" TEXT,
19
+ "sourceDeviceId" TEXT,
20
+ "commitSha" TEXT,
21
+ "trusted" BOOLEAN NOT NULL DEFAULT true,
22
+ "version" INTEGER NOT NULL DEFAULT 0,
23
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
24
+ "updatedAt" DATETIME NOT NULL,
25
+ CONSTRAINT "ProjectMemory_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
26
+ );
27
+
28
+ -- CreateTable
29
+ CREATE TABLE "MemoryEvent" (
30
+ "id" TEXT NOT NULL PRIMARY KEY,
31
+ "memoryId" TEXT NOT NULL,
32
+ "op" TEXT NOT NULL,
33
+ "actorKind" TEXT NOT NULL,
34
+ "actorId" TEXT,
35
+ "reason" TEXT,
36
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
37
+ CONSTRAINT "MemoryEvent_memoryId_fkey" FOREIGN KEY ("memoryId") REFERENCES "ProjectMemory" ("id") ON DELETE CASCADE ON UPDATE CASCADE
38
+ );
39
+
40
+ -- CreateTable
41
+ CREATE TABLE "MemoryLocalState" (
42
+ "memoryId" TEXT NOT NULL PRIMARY KEY,
43
+ "verdict" TEXT NOT NULL,
44
+ "verifiedHead" TEXT,
45
+ "lastVerifiedAt" DATETIME,
46
+ "lastUsedAt" DATETIME
47
+ );
48
+
49
+ -- CreateIndex
50
+ CREATE INDEX "ProjectMemory_projectId_status_idx" ON "ProjectMemory"("projectId", "status");
51
+
52
+ -- CreateIndex
53
+ CREATE INDEX "MemoryEvent_memoryId_createdAt_idx" ON "MemoryEvent"("memoryId", "createdAt");
54
+
@@ -0,0 +1,32 @@
1
+ -- ADR-0180 · sync memori: MemoryEvent.version/updatedAt, SyncState.entities (LOCAL-only)
2
+ -- RedefineTables
3
+ PRAGMA defer_foreign_keys=ON;
4
+ PRAGMA foreign_keys=OFF;
5
+ CREATE TABLE "new_MemoryEvent" (
6
+ "id" TEXT NOT NULL PRIMARY KEY,
7
+ "memoryId" TEXT NOT NULL,
8
+ "op" TEXT NOT NULL,
9
+ "actorKind" TEXT NOT NULL,
10
+ "actorId" TEXT,
11
+ "reason" TEXT,
12
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
13
+ "version" INTEGER NOT NULL DEFAULT 0,
14
+ "updatedAt" DATETIME NOT NULL,
15
+ CONSTRAINT "MemoryEvent_memoryId_fkey" FOREIGN KEY ("memoryId") REFERENCES "ProjectMemory" ("id") ON DELETE CASCADE ON UPDATE CASCADE
16
+ );
17
+ -- ADR-0180 · baris lama tak punya updatedAt: isi dengan createdAt (event append-only, tak pernah berubah).
18
+ INSERT INTO "new_MemoryEvent" ("actorId", "actorKind", "createdAt", "id", "memoryId", "op", "reason", "updatedAt") SELECT "actorId", "actorKind", "createdAt", "id", "memoryId", "op", "reason", "createdAt" FROM "MemoryEvent";
19
+ DROP TABLE "MemoryEvent";
20
+ ALTER TABLE "new_MemoryEvent" RENAME TO "MemoryEvent";
21
+ CREATE INDEX "MemoryEvent_memoryId_createdAt_idx" ON "MemoryEvent"("memoryId", "createdAt");
22
+ CREATE TABLE "new_SyncState" (
23
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT 1,
24
+ "cursor" TEXT NOT NULL DEFAULT '0',
25
+ "entities" TEXT NOT NULL DEFAULT ''
26
+ );
27
+ INSERT INTO "new_SyncState" ("cursor", "id") SELECT "cursor", "id" FROM "SyncState";
28
+ DROP TABLE "SyncState";
29
+ ALTER TABLE "new_SyncState" RENAME TO "SyncState";
30
+ PRAGMA foreign_keys=ON;
31
+ PRAGMA defer_foreign_keys=OFF;
32
+
@@ -37,6 +37,7 @@ model Project {
37
37
  portalChats PortalChatSession[] // SPEC-854 · ADR-0129 · percakapan portal klien project ini
38
38
  tasks Task[] // SPEC-945 · ADR-0150 · kartu kerja manusia di project ini
39
39
  qaReports QaReport[] // Workspace QA · laporan QA project ini
40
+ memories ProjectMemory[] // ADR-0178 · memori project bersama lintas runtime
40
41
  }
41
42
 
42
43
  model Spec {
@@ -438,6 +439,8 @@ model AgentToken {
438
439
  tokenHash String @unique
439
440
  tokenPrefix String
440
441
  capabilities Json
442
+ // ADR-0178 · allowlist project. null/[] = token tak boleh menyentuh route memori sama sekali.
443
+ projectIds Json?
441
444
  enabled Boolean @default(true)
442
445
  createdBy String?
443
446
  createdAt DateTime @default(now())
@@ -584,6 +587,8 @@ model SyncOutbox {
584
587
  model SyncState {
585
588
  id Int @id @default(1)
586
589
  cursor String @default("0")
590
+ // ADR-0180 · LOCAL-only: entitas sync OPSIONAL yang sudah di-catch-up mesin ini (dipisah koma).
591
+ entities String @default("")
587
592
  }
588
593
 
589
594
  // SPEC-270 · ADR-0067 · LOCAL-ONLY: antrean konflik dua-sisi menunggu keputusan manusia (modal).
@@ -1154,3 +1159,55 @@ model QaAttachment {
1154
1159
  @@index([ownerType, ownerId])
1155
1160
  @@index([syncState])
1156
1161
  }
1162
+
1163
+ // ADR-0178 · satu fakta per baris. content/anchors/scopePaths/kind TAK PERNAH diedit — koreksi =
1164
+ // baris baru dengan `supersedesId`. Hanya `status` yang bergerak, dan hanya naik (lattice).
1165
+ model ProjectMemory {
1166
+ id String @id @default(cuid())
1167
+ projectId String
1168
+ project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
1169
+ kind String // convention | gotcha | decision | fact
1170
+ content String
1171
+ scopePaths Json // string[] glob relatif root repo; [] = seluruh project
1172
+ anchors Json // [{path, blobSha, lines?}]
1173
+ status String // proposed | active | invalidated | rejected
1174
+ supersedesId String?
1175
+ reviewReason String? // decision | no-anchor | anchor-unverified | untrusted-source
1176
+ sourceRuntime String // claude | codex | external | human
1177
+ sourceSessionId String?
1178
+ sourceTokenId String?
1179
+ sourceDeviceId String? // diisi tahap sync
1180
+ commitSha String?
1181
+ trusted Boolean @default(true)
1182
+ version Int @default(0)
1183
+ createdAt DateTime @default(now())
1184
+ updatedAt DateTime @updatedAt
1185
+ events MemoryEvent[]
1186
+
1187
+ @@index([projectId, status])
1188
+ }
1189
+
1190
+ // ADR-0178 · jejak audit append-only. Tak pernah di-update atau dihapus kecuali ikut cascade.
1191
+ model MemoryEvent {
1192
+ id String @id @default(cuid())
1193
+ memoryId String
1194
+ memory ProjectMemory @relation(fields: [memoryId], references: [id], onDelete: Cascade)
1195
+ op String // propose | activate | reject | invalidate | supersede | reverify
1196
+ actorKind String // user | token | session | system
1197
+ actorId String?
1198
+ reason String?
1199
+ createdAt DateTime @default(now())
1200
+ version Int @default(0) // ADR-0180 · wajib bagi entitas sync
1201
+ updatedAt DateTime @updatedAt
1202
+
1203
+ @@index([memoryId, createdAt])
1204
+ }
1205
+
1206
+ // ADR-0178 · LOCAL-ONLY (tak pernah disync): hasil verifikasi jangkar bergantung HEAD mesin ini.
1207
+ model MemoryLocalState {
1208
+ memoryId String @id
1209
+ verdict String // valid | stale | unverifiable
1210
+ verifiedHead String?
1211
+ lastVerifiedAt DateTime?
1212
+ lastUsedAt DateTime?
1213
+ }
@@ -1 +1 @@
1
- import{e as C,j as a,as as A,a as y,c as b,d as w,S as H,N as V,aC as q,h as L,u as K,f as M,w as N,aA as O,A as _,aQ as Q,y as U,x as Y,p as Z,B as G,D as J}from"./index-DHVdBKua.js";import{R as n}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const X=[{mode:"backlog",label:"Rentang tanggal",hint:"backlog yang selesai di rentang itu"},{mode:"commit",label:"Rentang commit",hint:"perubahan repo antara dua revisi"},{mode:"version",label:"Versi rilis",hint:"perubahan yang masuk ke sebuah versi"}];function ee({p:t,onToast:o,onGenerated:g}){const[i,D]=n.useState("backlog"),[s,I]=n.useState(null),[h,f]=n.useState(""),[p,d]=n.useState(""),[x,B]=n.useState(""),[v,c]=n.useState(""),[j,u]=n.useState(""),[S,l]=n.useState(""),[m,R]=n.useState(!1);n.useEffect(()=>{let e=!0;return(async()=>{try{const r=await C.changelogSources(t.id);if(!e)return;I(r),f(r.defaultRange.from),d(r.defaultRange.to),r.tags[0]&&l(r.tags[0]),r.head&&c(r.head)}catch{}})(),()=>{e=!1}},[t.id]);const T=()=>i==="backlog"?{mode:i,from:h||void 0,to:p||void 0}:i==="commit"?{mode:i,fromSha:x,toSha:v}:{mode:i,fromTag:j||void 0,toTag:S},k=i==="backlog"?!0:i==="commit"?x.trim().length>=4&&v.trim().length>=4:S.trim().length>0;async function F(){R(!0);try{const e=await C.generateChangelog(t.id,T());o(e.generator==="agent"?"Changelog dibangkitkan":"Changelog dibangkitkan (draf ringkas)",e.generator==="agent"?"ok":"warn","file-text"),g==null||g(e)}catch(e){o(e.message||"Gagal membangkitkan changelog","err","x-circle")}finally{R(!1)}}const E=i==="version"&&s!==null&&s.tags.length===0,z=i==="commit"&&s!==null&&!!s.reason&&s.tags.length===0;return a.jsxs(A,{eyebrow:"changelog",title:"Ringkasan perubahan untuk pemakai",children:[a.jsx("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:"Teks pendek berorientasi pemakai — apa yang berubah bagi mereka, bukan apa yang disentuh di dalam kode."}),a.jsx("div",{style:{display:"flex",gap:6,marginBottom:12,flexWrap:"wrap"},children:X.map(e=>a.jsx(y,{size:"sm",variant:i===e.mode?"primary":"ghost",onClick:()=>D(e.mode),title:e.hint,children:e.label},e.mode))}),a.jsxs("div",{style:{display:"flex",gap:10,alignItems:"flex-end",flexWrap:"wrap",marginBottom:12},children:[i==="backlog"&&a.jsxs(a.Fragment,{children:[a.jsx(b,{label:"Dari tanggal",children:a.jsx(w,{"aria-label":"Dari tanggal",type:"date",value:h,onChange:e=>f(e.target.value)})}),a.jsx(b,{label:"Sampai tanggal",children:a.jsx(w,{"aria-label":"Sampai tanggal",type:"date",value:p,onChange:e=>d(e.target.value)})})]}),i==="commit"&&a.jsxs(a.Fragment,{children:[a.jsx(b,{label:"Dari revisi",children:a.jsx(w,{"aria-label":"Dari revisi",mono:!0,placeholder:"mis. v1.0.0 atau 4f2a1c9",value:x,onChange:e=>B(e.target.value)})}),a.jsx(b,{label:"Sampai revisi",children:a.jsx(w,{"aria-label":"Sampai revisi",mono:!0,placeholder:"mis. HEAD atau 9d3b77e",value:v,onChange:e=>c(e.target.value)})})]}),i==="version"&&a.jsxs(a.Fragment,{children:[a.jsx(b,{label:"Sejak versi",children:a.jsx(H,{"aria-label":"Sejak versi",value:j,onChange:e=>u(e.target.value),options:[{value:"",label:"versi sebelumnya"},...((s==null?void 0:s.tags)??[]).map(e=>({value:e,label:e}))]})}),a.jsx(b,{label:"Versi",children:a.jsx(H,{"aria-label":"Versi",value:S,onChange:e=>l(e.target.value),options:((s==null?void 0:s.tags)??[]).map(e=>({value:e,label:e}))})})]}),a.jsx(y,{leftIcon:"sparkles",onClick:()=>void F(),disabled:m||!k||E||z,children:m?"Membangkitkan…":"Bangkitkan"})]}),(E||z)&&a.jsx(V,{tone:"warn",children:s==null?void 0:s.reason})]})}const $=12,W={backlog:"rentang tanggal",commit:"rentang commit",version:"versi rilis"},ae=t=>new Date(t).toLocaleDateString("id-ID",{day:"numeric",month:"short",year:"numeric"});function te({c:t,active:o,onOpen:g}){return a.jsxs("div",{role:"button",tabIndex:0,onClick:g,onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),g())},style:{display:"flex",alignItems:"center",gap:10,padding:"9px 10px",cursor:"pointer",borderRadius:"var(--radius-sm)",borderBottom:"1px solid var(--border-hair)",background:o?"var(--brass-100)":"transparent"},children:[a.jsxs("div",{style:{flex:1,minWidth:0},children:[a.jsx("div",{style:{fontSize:13.5,fontWeight:500,color:"var(--text-strong)"},children:t.title}),a.jsxs("div",{style:{fontSize:11.5,color:"var(--text-subtle)",marginTop:2},children:[W[t.mode]??t.mode," · ",ae(t.createdAt)," · ",t.itemCount," perubahan"]})]}),a.jsx(G,{tone:t.generator==="agent"?"ok":"warn",size:"sm",children:t.generator==="agent"?"naratif":"draf ringkas"})]})}function re({p:t,onToast:o,initialChangelogId:g}){const[i,D]=n.useState([]),[s,I]=n.useState(0),h=q("changelog",t.id),[f,p]=L(h,"page",1,Y),[d,x]=L(h,"q","",Z),[B,v]=n.useState(!0),[c,j]=L(h,"selectedId",null,U),[u,S]=n.useState(null),l=n.useMemo(()=>i.find(e=>e.id===c)??((u==null?void 0:u.id)===c?u:null),[i,c,u]),m=n.useCallback(e=>{j(e?e.id:null),S(e)},[j]),[R,T]=n.useState(0);n.useEffect(()=>{let e=!0;const r=setTimeout(()=>{v(!0),C.listChangelogs(t.id,{q:d,page:f,limit:$}).then(P=>{e&&(D(P.items),I(P.total))}).catch(()=>{e&&(D([]),I(0))}).finally(()=>{e&&v(!1)})},d?220:0);return()=>{e=!1,clearTimeout(r)}},[t.id,d,f,R]),n.useEffect(()=>{if(!g)return;let e=!0;return C.getChangelog(t.id,g).then(r=>{e&&m(r)}).catch(()=>{e&&o("Rilis yang ditautkan tak ditemukan","warn","link-2-off")}),()=>{e=!1}},[t.id,g,o]);const k=J(s,f,$),{confirm:F,dialog:E}=K();async function z(e){try{if(!await F({title:`Hapus changelog "${e.title}"?`,message:"Rilis ini hilang dari riwayat project.",confirmLabel:"Hapus rilis",run:()=>C.deleteChangelog(t.id,e.id)}))return;c===e.id&&m(null),T(r=>r+1),o("Changelog dihapus","ok","trash-2")}catch{o("Gagal menghapus changelog","err","x-circle")}}return a.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:20},children:[a.jsx(ee,{p:t,onToast:o,onGenerated:e=>{m(e),p(1),T(r=>r+1)}}),a.jsxs(A,{eyebrow:"rilis",title:"Riwayat changelog",actions:a.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11.5,color:"var(--text-subtle)"},children:[s," rilis"]}),children:[a.jsx(w,{"aria-label":"Cari rilis",leftIcon:"search",placeholder:"cari judul atau isi rilis…",value:d,style:{width:"100%"},onChange:e=>{p(1),x(e.target.value)}}),a.jsxs("div",{"data-testid":"changelog-list",style:{maxHeight:340,overflowY:"auto",marginTop:10},children:[B&&i.length===0&&a.jsx(M,{kind:"loading",compact:!0}),!B&&i.length===0&&(d.trim()?a.jsx(M,{kind:"empty",icon:"search",compact:!0,title:"Tak ada rilis yang cocok",hint:`Tak ada rilis yang memuat “${d.trim()}”.`,action:()=>x(""),actionLabel:"Bersihkan pencarian",actionIcon:"x"}):a.jsx(M,{kind:"empty",icon:"megaphone",compact:!0,title:"Belum ada rilis",hint:"Bangkitkan changelog pertama project ini lewat kartu di atas."})),i.map(e=>a.jsx(te,{c:e,active:(l==null?void 0:l.id)===e.id,onOpen:()=>m(e)},e.id))]}),a.jsx(N,{page:k.page,pageCount:k.pageCount,total:s,from:k.from,to:k.to,onPage:p,unit:"rilis"})]}),l&&a.jsxs(A,{eyebrow:`rilis · ${W[l.mode]??l.mode}`,title:l.title,actions:a.jsxs("div",{className:"hn-row-actions",style:{display:"flex",gap:6},children:[a.jsx(y,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var e;(e=navigator.clipboard)==null||e.writeText(l.body),o("Changelog disalin","ok","copy")},children:"Salin"}),a.jsx(y,{as:"a",size:"sm",variant:"ghost",leftIcon:"download",download:!0,href:`${_.changelogItem(t.id,l.id)}?download=md`,"aria-label":"Unduh .md",children:"Unduh .md"}),a.jsx(y,{size:"sm",variant:"ghost",leftIcon:"link",onClick:()=>{var e;(e=navigator.clipboard)==null||e.writeText(Q(t.id,l.id)),o("Link changelog disalin","ok","link")},children:"Salin link"}),a.jsx(y,{size:"sm",variant:"ghost",leftIcon:"trash-2","aria-label":`Hapus ${l.title}`,onClick:()=>void z(l)})]}),children:[l.warning&&a.jsx(V,{tone:"warn",children:l.warning}),a.jsx(O,{text:l.body,name:"changelog.md"})]}),E]})}export{re as ChangelogScreen};
1
+ import{e as C,j as a,as as A,a as y,c as b,d as w,S as H,N as V,aC as q,h as L,u as K,f as M,w as N,aA as O,A as _,aQ as Q,y as U,x as Y,p as Z,B as G,D as J}from"./index-gNO91_qw.js";import{R as n}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const X=[{mode:"backlog",label:"Rentang tanggal",hint:"backlog yang selesai di rentang itu"},{mode:"commit",label:"Rentang commit",hint:"perubahan repo antara dua revisi"},{mode:"version",label:"Versi rilis",hint:"perubahan yang masuk ke sebuah versi"}];function ee({p:t,onToast:o,onGenerated:g}){const[i,D]=n.useState("backlog"),[s,I]=n.useState(null),[h,f]=n.useState(""),[p,d]=n.useState(""),[x,B]=n.useState(""),[v,c]=n.useState(""),[j,u]=n.useState(""),[S,l]=n.useState(""),[m,R]=n.useState(!1);n.useEffect(()=>{let e=!0;return(async()=>{try{const r=await C.changelogSources(t.id);if(!e)return;I(r),f(r.defaultRange.from),d(r.defaultRange.to),r.tags[0]&&l(r.tags[0]),r.head&&c(r.head)}catch{}})(),()=>{e=!1}},[t.id]);const T=()=>i==="backlog"?{mode:i,from:h||void 0,to:p||void 0}:i==="commit"?{mode:i,fromSha:x,toSha:v}:{mode:i,fromTag:j||void 0,toTag:S},k=i==="backlog"?!0:i==="commit"?x.trim().length>=4&&v.trim().length>=4:S.trim().length>0;async function F(){R(!0);try{const e=await C.generateChangelog(t.id,T());o(e.generator==="agent"?"Changelog dibangkitkan":"Changelog dibangkitkan (draf ringkas)",e.generator==="agent"?"ok":"warn","file-text"),g==null||g(e)}catch(e){o(e.message||"Gagal membangkitkan changelog","err","x-circle")}finally{R(!1)}}const E=i==="version"&&s!==null&&s.tags.length===0,z=i==="commit"&&s!==null&&!!s.reason&&s.tags.length===0;return a.jsxs(A,{eyebrow:"changelog",title:"Ringkasan perubahan untuk pemakai",children:[a.jsx("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:"Teks pendek berorientasi pemakai — apa yang berubah bagi mereka, bukan apa yang disentuh di dalam kode."}),a.jsx("div",{style:{display:"flex",gap:6,marginBottom:12,flexWrap:"wrap"},children:X.map(e=>a.jsx(y,{size:"sm",variant:i===e.mode?"primary":"ghost",onClick:()=>D(e.mode),title:e.hint,children:e.label},e.mode))}),a.jsxs("div",{style:{display:"flex",gap:10,alignItems:"flex-end",flexWrap:"wrap",marginBottom:12},children:[i==="backlog"&&a.jsxs(a.Fragment,{children:[a.jsx(b,{label:"Dari tanggal",children:a.jsx(w,{"aria-label":"Dari tanggal",type:"date",value:h,onChange:e=>f(e.target.value)})}),a.jsx(b,{label:"Sampai tanggal",children:a.jsx(w,{"aria-label":"Sampai tanggal",type:"date",value:p,onChange:e=>d(e.target.value)})})]}),i==="commit"&&a.jsxs(a.Fragment,{children:[a.jsx(b,{label:"Dari revisi",children:a.jsx(w,{"aria-label":"Dari revisi",mono:!0,placeholder:"mis. v1.0.0 atau 4f2a1c9",value:x,onChange:e=>B(e.target.value)})}),a.jsx(b,{label:"Sampai revisi",children:a.jsx(w,{"aria-label":"Sampai revisi",mono:!0,placeholder:"mis. HEAD atau 9d3b77e",value:v,onChange:e=>c(e.target.value)})})]}),i==="version"&&a.jsxs(a.Fragment,{children:[a.jsx(b,{label:"Sejak versi",children:a.jsx(H,{"aria-label":"Sejak versi",value:j,onChange:e=>u(e.target.value),options:[{value:"",label:"versi sebelumnya"},...((s==null?void 0:s.tags)??[]).map(e=>({value:e,label:e}))]})}),a.jsx(b,{label:"Versi",children:a.jsx(H,{"aria-label":"Versi",value:S,onChange:e=>l(e.target.value),options:((s==null?void 0:s.tags)??[]).map(e=>({value:e,label:e}))})})]}),a.jsx(y,{leftIcon:"sparkles",onClick:()=>void F(),disabled:m||!k||E||z,children:m?"Membangkitkan…":"Bangkitkan"})]}),(E||z)&&a.jsx(V,{tone:"warn",children:s==null?void 0:s.reason})]})}const $=12,W={backlog:"rentang tanggal",commit:"rentang commit",version:"versi rilis"},ae=t=>new Date(t).toLocaleDateString("id-ID",{day:"numeric",month:"short",year:"numeric"});function te({c:t,active:o,onOpen:g}){return a.jsxs("div",{role:"button",tabIndex:0,onClick:g,onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),g())},style:{display:"flex",alignItems:"center",gap:10,padding:"9px 10px",cursor:"pointer",borderRadius:"var(--radius-sm)",borderBottom:"1px solid var(--border-hair)",background:o?"var(--brass-100)":"transparent"},children:[a.jsxs("div",{style:{flex:1,minWidth:0},children:[a.jsx("div",{style:{fontSize:13.5,fontWeight:500,color:"var(--text-strong)"},children:t.title}),a.jsxs("div",{style:{fontSize:11.5,color:"var(--text-subtle)",marginTop:2},children:[W[t.mode]??t.mode," · ",ae(t.createdAt)," · ",t.itemCount," perubahan"]})]}),a.jsx(G,{tone:t.generator==="agent"?"ok":"warn",size:"sm",children:t.generator==="agent"?"naratif":"draf ringkas"})]})}function re({p:t,onToast:o,initialChangelogId:g}){const[i,D]=n.useState([]),[s,I]=n.useState(0),h=q("changelog",t.id),[f,p]=L(h,"page",1,Y),[d,x]=L(h,"q","",Z),[B,v]=n.useState(!0),[c,j]=L(h,"selectedId",null,U),[u,S]=n.useState(null),l=n.useMemo(()=>i.find(e=>e.id===c)??((u==null?void 0:u.id)===c?u:null),[i,c,u]),m=n.useCallback(e=>{j(e?e.id:null),S(e)},[j]),[R,T]=n.useState(0);n.useEffect(()=>{let e=!0;const r=setTimeout(()=>{v(!0),C.listChangelogs(t.id,{q:d,page:f,limit:$}).then(P=>{e&&(D(P.items),I(P.total))}).catch(()=>{e&&(D([]),I(0))}).finally(()=>{e&&v(!1)})},d?220:0);return()=>{e=!1,clearTimeout(r)}},[t.id,d,f,R]),n.useEffect(()=>{if(!g)return;let e=!0;return C.getChangelog(t.id,g).then(r=>{e&&m(r)}).catch(()=>{e&&o("Rilis yang ditautkan tak ditemukan","warn","link-2-off")}),()=>{e=!1}},[t.id,g,o]);const k=J(s,f,$),{confirm:F,dialog:E}=K();async function z(e){try{if(!await F({title:`Hapus changelog "${e.title}"?`,message:"Rilis ini hilang dari riwayat project.",confirmLabel:"Hapus rilis",run:()=>C.deleteChangelog(t.id,e.id)}))return;c===e.id&&m(null),T(r=>r+1),o("Changelog dihapus","ok","trash-2")}catch{o("Gagal menghapus changelog","err","x-circle")}}return a.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:20},children:[a.jsx(ee,{p:t,onToast:o,onGenerated:e=>{m(e),p(1),T(r=>r+1)}}),a.jsxs(A,{eyebrow:"rilis",title:"Riwayat changelog",actions:a.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11.5,color:"var(--text-subtle)"},children:[s," rilis"]}),children:[a.jsx(w,{"aria-label":"Cari rilis",leftIcon:"search",placeholder:"cari judul atau isi rilis…",value:d,style:{width:"100%"},onChange:e=>{p(1),x(e.target.value)}}),a.jsxs("div",{"data-testid":"changelog-list",style:{maxHeight:340,overflowY:"auto",marginTop:10},children:[B&&i.length===0&&a.jsx(M,{kind:"loading",compact:!0}),!B&&i.length===0&&(d.trim()?a.jsx(M,{kind:"empty",icon:"search",compact:!0,title:"Tak ada rilis yang cocok",hint:`Tak ada rilis yang memuat “${d.trim()}”.`,action:()=>x(""),actionLabel:"Bersihkan pencarian",actionIcon:"x"}):a.jsx(M,{kind:"empty",icon:"megaphone",compact:!0,title:"Belum ada rilis",hint:"Bangkitkan changelog pertama project ini lewat kartu di atas."})),i.map(e=>a.jsx(te,{c:e,active:(l==null?void 0:l.id)===e.id,onOpen:()=>m(e)},e.id))]}),a.jsx(N,{page:k.page,pageCount:k.pageCount,total:s,from:k.from,to:k.to,onPage:p,unit:"rilis"})]}),l&&a.jsxs(A,{eyebrow:`rilis · ${W[l.mode]??l.mode}`,title:l.title,actions:a.jsxs("div",{className:"hn-row-actions",style:{display:"flex",gap:6},children:[a.jsx(y,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var e;(e=navigator.clipboard)==null||e.writeText(l.body),o("Changelog disalin","ok","copy")},children:"Salin"}),a.jsx(y,{as:"a",size:"sm",variant:"ghost",leftIcon:"download",download:!0,href:`${_.changelogItem(t.id,l.id)}?download=md`,"aria-label":"Unduh .md",children:"Unduh .md"}),a.jsx(y,{size:"sm",variant:"ghost",leftIcon:"link",onClick:()=>{var e;(e=navigator.clipboard)==null||e.writeText(Q(t.id,l.id)),o("Link changelog disalin","ok","link")},children:"Salin link"}),a.jsx(y,{size:"sm",variant:"ghost",leftIcon:"trash-2","aria-label":`Hapus ${l.title}`,onClick:()=>void z(l)})]}),children:[l.warning&&a.jsx(V,{tone:"warn",children:l.warning}),a.jsx(O,{text:l.body,name:"changelog.md"})]}),E]})}export{re as ChangelogScreen};
@@ -1 +1 @@
1
- import{i as ie,j as e,b as re,I as E}from"./index-DHVdBKua.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const de="/assets/hnm-hero-rig-body-v01-DmbKJJHB.webp",ce="/assets/hnm-hero-rig-arm-ul-v01-CIAWAxFe.webp",he="/assets/hnm-hero-rig-arm-ur-v01-C0R0CZnp.webp",oe="/assets/hnm-hero-rig-arm-ml-v01-Kts3pjTf.webp",ge="/assets/hnm-hero-rig-arm-mr-v01-DQgnE6bD.webp",me="/assets/hnm-wayang-satria-alus-v01-CpfoXKTy.webp",ue="/assets/hnm-wayang-satria-gagah-v01-bLfIYAsv.webp",pe="/assets/hnm-wayang-putri-v01-F6p69kHq.webp",xe="/assets/hnm-wayang-panakawan-v01-1LGv-V8N.webp",q=[me,ue,pe,xe],z=a=>q[[...a].reduce((t,o)=>t+o.charCodeAt(0),0)%q.length],V=["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],C=a=>String(a).padStart(2,"0");function je(){return g.useMemo(()=>typeof window<"u"&&!!window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,[])}function Ne(){const[a,t]=g.useState(()=>new Date);return g.useEffect(()=>{const o=setInterval(()=>t(new Date),1e3);return()=>clearInterval(o)},[]),a}function ye(a,t){const[o,m]=g.useState(""),p=a.join("|");return g.useEffect(()=>{if(t||a.length===0){m(a[0]??"");return}let x=0,h=0,r=null,d=null;const l=()=>{const y=a[x%a.length]??"";h=0,r=setInterval(()=>{h++,m(y.slice(0,h)),h>=y.length&&r&&(clearInterval(r),r=null,d=setTimeout(()=>{x++,l()},3200))},26)};return l(),()=>{r&&clearInterval(r),d&&clearTimeout(d)}},[p,t]),o}function S(a,t){const[o,m]=g.useState(t?a:0);return g.useEffect(()=>{if(t){m(a);return}const p=performance.now(),x=900;let h=0;const r=d=>{const l=Math.min(1,(d-p)/x);m(Math.round(a*(1-Math.pow(1-l,3)))),l<1&&(h=requestAnimationFrame(r))};return h=requestAnimationFrame(r),()=>cancelAnimationFrame(h)},[a,t]),o}function M({icon:a,tone:t,label:o,value:m,sub:p}){return e.jsxs("div",{className:"hn-dlg-kpi",children:[e.jsx("span",{className:`hn-dlg-kpi-ic hn-dlg-tone-${t}`,children:e.jsx(E,{name:a,size:17})}),e.jsxs("span",{style:{minWidth:0},children:[e.jsx("span",{className:"hn-dlg-kpi-l",children:o}),e.jsx("span",{className:"hn-dlg-kpi-v",children:m}),e.jsx("span",{className:"hn-dlg-kpi-s",children:p})]})]})}function ke({projects:a,backlog:t,sessions:o,onOpenSession:m,onOpenProject:p,onGoto:x,onExit:h}){const r=je(),d=Ne();g.useEffect(()=>{const n=s=>{s.key==="Escape"&&h()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[h]);const l=o.filter(n=>!n.exited).sort((n,s)=>n.id.localeCompare(s.id)),y=new Set(l.map(n=>n.projectId)),f=a.filter(n=>!y.has(n.id)),R=l.filter(n=>!!n.decision&&!n.deciding).length,F=t.filter(n=>ie(n.startedAt)).length,Q=S(a.length,r),X=S(F,r),Z=S(l.length,r),_=S(R,r),ee=ye([l.length>0?`HANOMAN ONLINE · ${l.length} SESI HIDUP`:"HANOMAN ONLINE · KELIR SUNYI",`${F} TASK DIKERJAKAN HARI INI`,R>0?`${R} SESI MENUNGGU JAWABANMU`:"SEMUA SISTEM NORMAL",`${a.length} PROYEK DALAM PANTAUAN`],r),j={done:0,executing:0,planned:0,spec:0};for(const n of t)n.stage==="done"?j.done++:n.stage==="executing"?j.executing++:n.stage==="planned"?j.planned++:j.spec++;const D=t.length,ne=[{key:"executing",cls:"wind",label:"Execute"},{key:"done",cls:"leaf",label:"Done"},{key:"planned",cls:"amber",label:"Plan"},{key:"spec",cls:"brass",label:"Spec"}];let L=0;const O=ne.map(n=>{const s=D?j[n.key]/D*100:0,u={...n,n:j[n.key],frac:s,offset:25-L};return L+=s,u}),v=[];for(let n=6;n>=0;n--){const s=new Date(d.getFullYear(),d.getMonth(),d.getDate()-n),u=t.filter(i=>{if(!i.startedAt)return!1;const c=new Date(i.startedAt);return c.getFullYear()===s.getFullYear()&&c.getMonth()===s.getMonth()&&c.getDate()===s.getDate()}).length;v.push({label:`${s.getDate()} ${V[s.getMonth()]}`,n:u})}const $=Math.max(1,...v.map(n=>n.n)),se=v.map((n,s)=>`${32+s*35},${78-n.n/$*60}`).join(" "),ae=`${l.map(n=>n.id).join("|")}#${f.map(n=>n.id).join("|")}`,H=g.useRef(null),[P,W]=g.useState([]);g.useLayoutEffect(()=>{const n=H.current;if(!n||l.length===0&&f.length===0){W([]);return}const s=()=>{var J;const i=n.getBoundingClientRect();if(i.width<60)return;const c=(J=n.querySelector(".hn-dlg-hero-art"))==null?void 0:J.getBoundingClientRect(),b=c?c.left+c.width/2-i.left:i.width/2,w={};n.querySelectorAll("[data-hand]").forEach(N=>{const A=N.getBoundingClientRect();w[N.dataset.hand??""]={x:A.left+A.width/2-i.left,y:A.top+A.height/2-i.top}});const k={x:b,y:c?c.top-i.top+c.height*.36:i.height*.35},G=[];n.querySelectorAll(".hn-dlg-prj").forEach(N=>{const U=(N.querySelector(".hn-dlg-puppet img")??N).getBoundingClientRect(),T=U.left+U.width/2-i.left,K=U.top-i.top+1,B=!N.hasAttribute("data-puppet"),te=T<b?"l":"r",I=w[(B?"m":"u")+te]??k,le=B?Math.max(I.y,K)+26:Math.min(I.y,K)-16;G.push({d:`M ${I.x.toFixed(1)} ${I.y.toFixed(1)} Q ${((I.x+T)/2).toFixed(1)} ${le.toFixed(1)}, ${T.toFixed(1)} ${K.toFixed(1)}`,slack:B})}),W(G)};if(s(),typeof ResizeObserver>"u")return;const u=new ResizeObserver(s);return u.observe(n),()=>u.disconnect()},[ae,l.length,f.length]);const Y=a.slice(0,6).map(n=>({id:n.id,name:n.name,text:n.activity,commit:n.commit,live:y.has(n.id)}));return e.jsxs("div",{className:"hn-dlg",children:[e.jsxs("div",{className:"hn-dlg-top hn-wrap-mobile",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,minWidth:0},children:[e.jsx("img",{className:"hn-dlg-blencong",src:re,alt:"","aria-hidden":"true","data-lit":l.length>0||void 0}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h2",{className:"hn-dlg-title",children:"Dalang Hanoman"}),e.jsx("p",{className:"hn-dlg-boot","aria-live":"off",children:ee})]})]}),e.jsxs("div",{className:"hn-dlg-chips",children:[e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"calendar",size:13}),d.getDate()," ",V[d.getMonth()]," ",d.getFullYear()]}),e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"clock",size:13}),C(d.getHours()),":",C(d.getMinutes()),":",C(d.getSeconds())]}),e.jsx("button",{type:"button",className:"hn-dlg-exit",onClick:h,"aria-label":"Keluar dari panggung (Esc)",children:e.jsx(E,{name:"x",size:14})})]})]}),e.jsxs("div",{className:"hn-dlg-kpis",children:[e.jsx(M,{icon:"layout-grid",tone:"wind",label:"TOTAL PROYEK",value:Q,sub:"dalam pantauan"}),e.jsx(M,{icon:"check-circle-2",tone:"leaf",label:"TASK HARI INI",value:X,sub:"mulai dikerjakan"}),e.jsx(M,{icon:"activity",tone:"brass",label:"SESI BERJALAN",value:Z,sub:"wayang dimainkan"}),e.jsx(M,{icon:"hand",tone:"amber",label:"MENUNGGU KAMU",value:_,sub:"butuh keputusan"})]}),e.jsxs("div",{className:"hn-dlg-grid hn-grid-mobile",children:[e.jsxs("div",{style:{minWidth:0},children:[e.jsxs("div",{className:"hn-dlg-hero",ref:H,children:[e.jsxs("svg",{className:"hn-dlg-hud",viewBox:"0 0 330 330","aria-hidden":"true",children:[e.jsx("g",{className:"hn-dlg-hud-a",children:e.jsx("circle",{cx:"165",cy:"165",r:"150",strokeDasharray:"3 14"})}),e.jsx("g",{className:"hn-dlg-hud-b",children:e.jsx("circle",{cx:"165",cy:"165",r:"126",strokeDasharray:"40 22"})})]}),P.length>0&&e.jsx("svg",{className:"hn-dlg-threads","aria-hidden":"true",focusable:"false",children:P.map((n,s)=>e.jsx("path",{d:n.d,className:n.slack?"hn-dlg-thread--slack":void 0,style:n.slack?void 0:{animationDelay:`${s%6*.3}s`}},s))}),e.jsx("div",{className:"hn-dlg-scan","aria-hidden":"true"}),e.jsxs("div",{className:"hn-dlg-hero-art","aria-hidden":"true",children:[e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ul",src:ce,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ur",src:he,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ml",src:oe,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--mr",src:ge,alt:""}),e.jsx("img",{className:"hn-dlg-rig-body",src:de,alt:""}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ul"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ur"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ml"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"mr"})]}),l.length>0||f.length>0?e.jsxs("div",{className:"hn-dlg-cards",role:"list","aria-label":"Wayang project",children:[l.map((n,s)=>{var w;const u=((w=a.find(k=>k.id===n.projectId))==null?void 0:w.name)??n.projectId,i=n.specId?t.find(k=>k.id===n.specId):void 0,c=!!n.decision&&!n.deciding,b=c?"menunggu jawabanmu":i?`${i.id} · ${i.stage}`:n.flow??"sesi terminal";return e.jsxs("button",{type:"button",className:"hn-dlg-prj","data-puppet":!0,"data-waiting":c||void 0,onClick:()=>m(n.id),"aria-label":`Buka terminal — ${u}, ${b}`,children:[e.jsx("span",{className:c?"hn-dlg-puppet hn-dlg-puppet--still":"hn-dlg-puppet",style:{animationDelay:`${s%6*.6}s`},children:e.jsx("img",{src:z(n.projectId),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:u}),e.jsx("span",{className:c?"hn-dlg-prj-sub hn-dlg-prj-sub--amber":"hn-dlg-prj-sub",children:b})]},n.id)}),f.map(n=>e.jsxs("button",{type:"button",className:"hn-dlg-prj hn-dlg-prj--off",onClick:()=>p(n),"aria-label":`Buka project ${n.name}`,children:[e.jsx("span",{className:"hn-dlg-puppet hn-dlg-puppet--still",children:e.jsx("img",{src:z(n.id),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:n.name}),e.jsx("span",{className:"hn-dlg-prj-sub hn-dlg-prj-sub--off",children:"tersandar di debog"})]},n.id))]}):e.jsxs("div",{className:"hn-dlg-empty",children:[e.jsx("div",{children:"Panggung sunyi — belum ada project di workspace."}),e.jsx("div",{children:"Tambahkan project dan sang dalang mengangkat wayangnya."})]})]}),e.jsxs("button",{type:"button",className:"hn-dlg-cmd",onClick:()=>x("terminal"),"aria-label":"Buka terminal — pusat kendali sesi",children:[e.jsx("span",{className:"hn-dlg-mic","aria-hidden":"true"}),e.jsxs("span",{className:"hn-dlg-cmd-t",children:[e.jsx("b",{children:"Perintah dalang"})," — buka Terminal untuk mengarahkan sesi yang berjalan…"]}),e.jsx("span",{className:"hn-dlg-cmd-k",children:"Terminal"})]})]}),e.jsxs("aside",{className:"hn-dlg-rail",children:[e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"AKTIVITAS TERAKHIR"}),Y.length===0?e.jsx("div",{className:"hn-dlg-mut",children:"Belum ada project."}):Y.map(n=>e.jsxs("div",{className:"hn-dlg-act",children:[e.jsx("span",{className:n.live?"hn-dlg-dot hn-dlg-dot--on":"hn-dlg-dot"}),e.jsxs("span",{className:"hn-dlg-act-x",children:[e.jsx("b",{children:n.name})," ",n.text]})]},n.id))]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DISTRIBUSI BACKLOG"}),e.jsxs("div",{className:"hn-dlg-donut-wrap",children:[e.jsxs("div",{className:"hn-dlg-donut",children:[e.jsxs("svg",{viewBox:"0 0 42 42",width:"112",height:"112","aria-hidden":"true",children:[e.jsx("circle",{className:"hn-dlg-ring",cx:"21",cy:"21",r:"15.9",strokeWidth:"5"}),O.map(n=>n.frac>0&&e.jsx("circle",{className:`hn-dlg-seg hn-dlg-seg--${n.cls}`,cx:"21",cy:"21",r:"15.9",strokeWidth:"5",strokeDasharray:`${n.frac} ${100-n.frac}`,strokeDashoffset:n.offset},n.key))]}),e.jsxs("div",{className:"hn-dlg-donut-c",children:[e.jsx("b",{children:D}),e.jsx("span",{children:"backlog"})]})]}),e.jsx("div",{className:"hn-dlg-leg",children:O.map(n=>e.jsxs("span",{children:[e.jsx("i",{className:`hn-dlg-seg--${n.cls}`}),n.label," ",e.jsx("b",{children:n.n})]},n.key))})]})]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DIMULAI · 7 HARI"}),e.jsxs("svg",{viewBox:"0 0 260 100",className:"hn-dlg-chart","aria-hidden":"true",children:[e.jsx("line",{x1:"24",y1:"18",x2:"252",y2:"18"}),e.jsx("line",{x1:"24",y1:"48",x2:"252",y2:"48"}),e.jsx("line",{x1:"24",y1:"78",x2:"252",y2:"78"}),e.jsx("text",{x:"8",y:"21",children:$}),e.jsx("text",{x:"10",y:"81",children:"0"}),e.jsx("polyline",{className:"hn-dlg-trend",points:se}),v.map((n,s)=>e.jsx("circle",{cx:32+s*35,cy:78-n.n/$*60,r:"2.4"},s)),v.map((n,s)=>s%2===0?e.jsx("text",{x:22+s*35,y:"94",children:n.label},`l${s}`):null)]})]})]})]}),e.jsx("div",{className:"hn-dlg-foot",children:"◈  HANOMAN · ORKESTRASI CERDAS · EKSEKUSI SEMPURNA  ◈"})]})}export{ke as DalangHanomanScreen};
1
+ import{i as ie,j as e,b as re,I as E}from"./index-gNO91_qw.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const de="/assets/hnm-hero-rig-body-v01-DmbKJJHB.webp",ce="/assets/hnm-hero-rig-arm-ul-v01-CIAWAxFe.webp",he="/assets/hnm-hero-rig-arm-ur-v01-C0R0CZnp.webp",oe="/assets/hnm-hero-rig-arm-ml-v01-Kts3pjTf.webp",ge="/assets/hnm-hero-rig-arm-mr-v01-DQgnE6bD.webp",me="/assets/hnm-wayang-satria-alus-v01-CpfoXKTy.webp",ue="/assets/hnm-wayang-satria-gagah-v01-bLfIYAsv.webp",pe="/assets/hnm-wayang-putri-v01-F6p69kHq.webp",xe="/assets/hnm-wayang-panakawan-v01-1LGv-V8N.webp",q=[me,ue,pe,xe],z=a=>q[[...a].reduce((t,o)=>t+o.charCodeAt(0),0)%q.length],V=["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],C=a=>String(a).padStart(2,"0");function je(){return g.useMemo(()=>typeof window<"u"&&!!window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,[])}function Ne(){const[a,t]=g.useState(()=>new Date);return g.useEffect(()=>{const o=setInterval(()=>t(new Date),1e3);return()=>clearInterval(o)},[]),a}function ye(a,t){const[o,m]=g.useState(""),p=a.join("|");return g.useEffect(()=>{if(t||a.length===0){m(a[0]??"");return}let x=0,h=0,r=null,d=null;const l=()=>{const y=a[x%a.length]??"";h=0,r=setInterval(()=>{h++,m(y.slice(0,h)),h>=y.length&&r&&(clearInterval(r),r=null,d=setTimeout(()=>{x++,l()},3200))},26)};return l(),()=>{r&&clearInterval(r),d&&clearTimeout(d)}},[p,t]),o}function S(a,t){const[o,m]=g.useState(t?a:0);return g.useEffect(()=>{if(t){m(a);return}const p=performance.now(),x=900;let h=0;const r=d=>{const l=Math.min(1,(d-p)/x);m(Math.round(a*(1-Math.pow(1-l,3)))),l<1&&(h=requestAnimationFrame(r))};return h=requestAnimationFrame(r),()=>cancelAnimationFrame(h)},[a,t]),o}function M({icon:a,tone:t,label:o,value:m,sub:p}){return e.jsxs("div",{className:"hn-dlg-kpi",children:[e.jsx("span",{className:`hn-dlg-kpi-ic hn-dlg-tone-${t}`,children:e.jsx(E,{name:a,size:17})}),e.jsxs("span",{style:{minWidth:0},children:[e.jsx("span",{className:"hn-dlg-kpi-l",children:o}),e.jsx("span",{className:"hn-dlg-kpi-v",children:m}),e.jsx("span",{className:"hn-dlg-kpi-s",children:p})]})]})}function ke({projects:a,backlog:t,sessions:o,onOpenSession:m,onOpenProject:p,onGoto:x,onExit:h}){const r=je(),d=Ne();g.useEffect(()=>{const n=s=>{s.key==="Escape"&&h()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[h]);const l=o.filter(n=>!n.exited).sort((n,s)=>n.id.localeCompare(s.id)),y=new Set(l.map(n=>n.projectId)),f=a.filter(n=>!y.has(n.id)),R=l.filter(n=>!!n.decision&&!n.deciding).length,F=t.filter(n=>ie(n.startedAt)).length,Q=S(a.length,r),X=S(F,r),Z=S(l.length,r),_=S(R,r),ee=ye([l.length>0?`HANOMAN ONLINE · ${l.length} SESI HIDUP`:"HANOMAN ONLINE · KELIR SUNYI",`${F} TASK DIKERJAKAN HARI INI`,R>0?`${R} SESI MENUNGGU JAWABANMU`:"SEMUA SISTEM NORMAL",`${a.length} PROYEK DALAM PANTAUAN`],r),j={done:0,executing:0,planned:0,spec:0};for(const n of t)n.stage==="done"?j.done++:n.stage==="executing"?j.executing++:n.stage==="planned"?j.planned++:j.spec++;const D=t.length,ne=[{key:"executing",cls:"wind",label:"Execute"},{key:"done",cls:"leaf",label:"Done"},{key:"planned",cls:"amber",label:"Plan"},{key:"spec",cls:"brass",label:"Spec"}];let L=0;const O=ne.map(n=>{const s=D?j[n.key]/D*100:0,u={...n,n:j[n.key],frac:s,offset:25-L};return L+=s,u}),v=[];for(let n=6;n>=0;n--){const s=new Date(d.getFullYear(),d.getMonth(),d.getDate()-n),u=t.filter(i=>{if(!i.startedAt)return!1;const c=new Date(i.startedAt);return c.getFullYear()===s.getFullYear()&&c.getMonth()===s.getMonth()&&c.getDate()===s.getDate()}).length;v.push({label:`${s.getDate()} ${V[s.getMonth()]}`,n:u})}const $=Math.max(1,...v.map(n=>n.n)),se=v.map((n,s)=>`${32+s*35},${78-n.n/$*60}`).join(" "),ae=`${l.map(n=>n.id).join("|")}#${f.map(n=>n.id).join("|")}`,H=g.useRef(null),[P,W]=g.useState([]);g.useLayoutEffect(()=>{const n=H.current;if(!n||l.length===0&&f.length===0){W([]);return}const s=()=>{var J;const i=n.getBoundingClientRect();if(i.width<60)return;const c=(J=n.querySelector(".hn-dlg-hero-art"))==null?void 0:J.getBoundingClientRect(),b=c?c.left+c.width/2-i.left:i.width/2,w={};n.querySelectorAll("[data-hand]").forEach(N=>{const A=N.getBoundingClientRect();w[N.dataset.hand??""]={x:A.left+A.width/2-i.left,y:A.top+A.height/2-i.top}});const k={x:b,y:c?c.top-i.top+c.height*.36:i.height*.35},G=[];n.querySelectorAll(".hn-dlg-prj").forEach(N=>{const U=(N.querySelector(".hn-dlg-puppet img")??N).getBoundingClientRect(),T=U.left+U.width/2-i.left,K=U.top-i.top+1,B=!N.hasAttribute("data-puppet"),te=T<b?"l":"r",I=w[(B?"m":"u")+te]??k,le=B?Math.max(I.y,K)+26:Math.min(I.y,K)-16;G.push({d:`M ${I.x.toFixed(1)} ${I.y.toFixed(1)} Q ${((I.x+T)/2).toFixed(1)} ${le.toFixed(1)}, ${T.toFixed(1)} ${K.toFixed(1)}`,slack:B})}),W(G)};if(s(),typeof ResizeObserver>"u")return;const u=new ResizeObserver(s);return u.observe(n),()=>u.disconnect()},[ae,l.length,f.length]);const Y=a.slice(0,6).map(n=>({id:n.id,name:n.name,text:n.activity,commit:n.commit,live:y.has(n.id)}));return e.jsxs("div",{className:"hn-dlg",children:[e.jsxs("div",{className:"hn-dlg-top hn-wrap-mobile",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,minWidth:0},children:[e.jsx("img",{className:"hn-dlg-blencong",src:re,alt:"","aria-hidden":"true","data-lit":l.length>0||void 0}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h2",{className:"hn-dlg-title",children:"Dalang Hanoman"}),e.jsx("p",{className:"hn-dlg-boot","aria-live":"off",children:ee})]})]}),e.jsxs("div",{className:"hn-dlg-chips",children:[e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"calendar",size:13}),d.getDate()," ",V[d.getMonth()]," ",d.getFullYear()]}),e.jsxs("span",{className:"hn-dlg-chip",children:[e.jsx(E,{name:"clock",size:13}),C(d.getHours()),":",C(d.getMinutes()),":",C(d.getSeconds())]}),e.jsx("button",{type:"button",className:"hn-dlg-exit",onClick:h,"aria-label":"Keluar dari panggung (Esc)",children:e.jsx(E,{name:"x",size:14})})]})]}),e.jsxs("div",{className:"hn-dlg-kpis",children:[e.jsx(M,{icon:"layout-grid",tone:"wind",label:"TOTAL PROYEK",value:Q,sub:"dalam pantauan"}),e.jsx(M,{icon:"check-circle-2",tone:"leaf",label:"TASK HARI INI",value:X,sub:"mulai dikerjakan"}),e.jsx(M,{icon:"activity",tone:"brass",label:"SESI BERJALAN",value:Z,sub:"wayang dimainkan"}),e.jsx(M,{icon:"hand",tone:"amber",label:"MENUNGGU KAMU",value:_,sub:"butuh keputusan"})]}),e.jsxs("div",{className:"hn-dlg-grid hn-grid-mobile",children:[e.jsxs("div",{style:{minWidth:0},children:[e.jsxs("div",{className:"hn-dlg-hero",ref:H,children:[e.jsxs("svg",{className:"hn-dlg-hud",viewBox:"0 0 330 330","aria-hidden":"true",children:[e.jsx("g",{className:"hn-dlg-hud-a",children:e.jsx("circle",{cx:"165",cy:"165",r:"150",strokeDasharray:"3 14"})}),e.jsx("g",{className:"hn-dlg-hud-b",children:e.jsx("circle",{cx:"165",cy:"165",r:"126",strokeDasharray:"40 22"})})]}),P.length>0&&e.jsx("svg",{className:"hn-dlg-threads","aria-hidden":"true",focusable:"false",children:P.map((n,s)=>e.jsx("path",{d:n.d,className:n.slack?"hn-dlg-thread--slack":void 0,style:n.slack?void 0:{animationDelay:`${s%6*.3}s`}},s))}),e.jsx("div",{className:"hn-dlg-scan","aria-hidden":"true"}),e.jsxs("div",{className:"hn-dlg-hero-art","aria-hidden":"true",children:[e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ul",src:ce,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ur",src:he,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--ml",src:oe,alt:""}),e.jsx("img",{className:"hn-dlg-rig-arm hn-dlg-rig-arm--mr",src:ge,alt:""}),e.jsx("img",{className:"hn-dlg-rig-body",src:de,alt:""}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ul"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ur"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"ml"}),e.jsx("span",{className:"hn-dlg-hand","data-hand":"mr"})]}),l.length>0||f.length>0?e.jsxs("div",{className:"hn-dlg-cards",role:"list","aria-label":"Wayang project",children:[l.map((n,s)=>{var w;const u=((w=a.find(k=>k.id===n.projectId))==null?void 0:w.name)??n.projectId,i=n.specId?t.find(k=>k.id===n.specId):void 0,c=!!n.decision&&!n.deciding,b=c?"menunggu jawabanmu":i?`${i.id} · ${i.stage}`:n.flow??"sesi terminal";return e.jsxs("button",{type:"button",className:"hn-dlg-prj","data-puppet":!0,"data-waiting":c||void 0,onClick:()=>m(n.id),"aria-label":`Buka terminal — ${u}, ${b}`,children:[e.jsx("span",{className:c?"hn-dlg-puppet hn-dlg-puppet--still":"hn-dlg-puppet",style:{animationDelay:`${s%6*.6}s`},children:e.jsx("img",{src:z(n.projectId),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:u}),e.jsx("span",{className:c?"hn-dlg-prj-sub hn-dlg-prj-sub--amber":"hn-dlg-prj-sub",children:b})]},n.id)}),f.map(n=>e.jsxs("button",{type:"button",className:"hn-dlg-prj hn-dlg-prj--off",onClick:()=>p(n),"aria-label":`Buka project ${n.name}`,children:[e.jsx("span",{className:"hn-dlg-puppet hn-dlg-puppet--still",children:e.jsx("img",{src:z(n.id),alt:"","aria-hidden":"true"})}),e.jsx("span",{className:"hn-dlg-prj-name",children:n.name}),e.jsx("span",{className:"hn-dlg-prj-sub hn-dlg-prj-sub--off",children:"tersandar di debog"})]},n.id))]}):e.jsxs("div",{className:"hn-dlg-empty",children:[e.jsx("div",{children:"Panggung sunyi — belum ada project di workspace."}),e.jsx("div",{children:"Tambahkan project dan sang dalang mengangkat wayangnya."})]})]}),e.jsxs("button",{type:"button",className:"hn-dlg-cmd",onClick:()=>x("terminal"),"aria-label":"Buka terminal — pusat kendali sesi",children:[e.jsx("span",{className:"hn-dlg-mic","aria-hidden":"true"}),e.jsxs("span",{className:"hn-dlg-cmd-t",children:[e.jsx("b",{children:"Perintah dalang"})," — buka Terminal untuk mengarahkan sesi yang berjalan…"]}),e.jsx("span",{className:"hn-dlg-cmd-k",children:"Terminal"})]})]}),e.jsxs("aside",{className:"hn-dlg-rail",children:[e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"AKTIVITAS TERAKHIR"}),Y.length===0?e.jsx("div",{className:"hn-dlg-mut",children:"Belum ada project."}):Y.map(n=>e.jsxs("div",{className:"hn-dlg-act",children:[e.jsx("span",{className:n.live?"hn-dlg-dot hn-dlg-dot--on":"hn-dlg-dot"}),e.jsxs("span",{className:"hn-dlg-act-x",children:[e.jsx("b",{children:n.name})," ",n.text]})]},n.id))]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DISTRIBUSI BACKLOG"}),e.jsxs("div",{className:"hn-dlg-donut-wrap",children:[e.jsxs("div",{className:"hn-dlg-donut",children:[e.jsxs("svg",{viewBox:"0 0 42 42",width:"112",height:"112","aria-hidden":"true",children:[e.jsx("circle",{className:"hn-dlg-ring",cx:"21",cy:"21",r:"15.9",strokeWidth:"5"}),O.map(n=>n.frac>0&&e.jsx("circle",{className:`hn-dlg-seg hn-dlg-seg--${n.cls}`,cx:"21",cy:"21",r:"15.9",strokeWidth:"5",strokeDasharray:`${n.frac} ${100-n.frac}`,strokeDashoffset:n.offset},n.key))]}),e.jsxs("div",{className:"hn-dlg-donut-c",children:[e.jsx("b",{children:D}),e.jsx("span",{children:"backlog"})]})]}),e.jsx("div",{className:"hn-dlg-leg",children:O.map(n=>e.jsxs("span",{children:[e.jsx("i",{className:`hn-dlg-seg--${n.cls}`}),n.label," ",e.jsx("b",{children:n.n})]},n.key))})]})]}),e.jsxs("div",{className:"hn-dlg-card",children:[e.jsx("div",{className:"hn-dlg-rt",children:"DIMULAI · 7 HARI"}),e.jsxs("svg",{viewBox:"0 0 260 100",className:"hn-dlg-chart","aria-hidden":"true",children:[e.jsx("line",{x1:"24",y1:"18",x2:"252",y2:"18"}),e.jsx("line",{x1:"24",y1:"48",x2:"252",y2:"48"}),e.jsx("line",{x1:"24",y1:"78",x2:"252",y2:"78"}),e.jsx("text",{x:"8",y:"21",children:$}),e.jsx("text",{x:"10",y:"81",children:"0"}),e.jsx("polyline",{className:"hn-dlg-trend",points:se}),v.map((n,s)=>e.jsx("circle",{cx:32+s*35,cy:78-n.n/$*60,r:"2.4"},s)),v.map((n,s)=>s%2===0?e.jsx("text",{x:22+s*35,y:"94",children:n.label},`l${s}`):null)]})]})]})]}),e.jsx("div",{className:"hn-dlg-foot",children:"◈  HANOMAN · ORKESTRASI CERDAS · EKSEKUSI SEMPURNA  ◈"})]})}export{ke as DalangHanomanScreen};
@@ -1 +1 @@
1
- import{j as e,M as r,ay as d,aA as a,f as x}from"./index-DHVdBKua.js";import"./react-DfGhg7ZW.js";function m({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{m as D};
1
+ import{j as e,M as r,ay as d,aA as a,f as x}from"./index-gNO91_qw.js";import"./react-DfGhg7ZW.js";function m({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{m as D};
@@ -1,3 +1,3 @@
1
- import{h as re,u as oe,e as y,j as e,v as le,as as T,ao as de,a as j,f as b,aP as ce,I as k,B as $,ay as xe,aA as A,p as pe,aC as ue}from"./index-DHVdBKua.js";import{R as l}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function J(s){let a={...s,kids:s.kids.map(J)};for(;!a.cat&&a.kids.length===1;){const i=a.kids[0];a={...i,label:a.label+"/"+i.label}}return a}function G(s){const a={path:"",kids:[]};for(const i of s){if(i.cat==="."){a.kids.push({path:".",label:".",cat:i,kids:[]});continue}let r=a;for(const x of i.cat.split("/")){const g=r.path?r.path+"/"+x:x;let d=r.kids.find(t=>t.path===g);d||(d={path:g,label:x,kids:[]},r.kids.push(d)),r=d}r.cat=i}return a.kids.map(J)}function O(s){const a=s.find(i=>i.scored&&i.linked)??s.find(i=>i.scored)??s[0];return a&&a.files[0]?`${a.cat}/${a.files[0]}`:""}function I({node:s,selected:a,onSelect:i,depth:r=0}){var h,u,p;const[x,g]=l.useState(!1),d=((h=s.cat)==null?void 0:h.scored)??!0,t=((u=s.cat)==null?void 0:u.linked)??!0;return e.jsxs("div",{style:r===0?{borderBottom:"1px solid var(--border-hair)"}:void 0,children:[e.jsxs("button",{onClick:()=>g(c=>!c),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"9px 6px",paddingLeft:6+r*12,border:"none",background:"transparent",cursor:"pointer",textAlign:"left"},children:[e.jsx(k,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(k,{name:"folder",size:15,color:d?t?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:"var(--text-strong)",fontWeight:500},children:[s.label,"/"]}),e.jsx("span",{style:{flex:1}}),s.cat&&d&&(s.cat.linked?e.jsx(k,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(k,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),x&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:1,paddingBottom:4},children:[s.kids.map(c=>e.jsx(I,{node:c,selected:a,onSelect:i,depth:r+1},c.path)),(p=s.cat)==null?void 0:p.files.map(c=>{const f=s.path+"/"+c,v=f===a;return e.jsxs("button",{onClick:()=>i(f),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"6px 8px",paddingLeft:18+r*12,borderRadius:"var(--radius-sm)",border:"none",cursor:"pointer",textAlign:"left",background:v?"var(--brass-100)":"transparent"},children:[e.jsx(k,{name:"file-text",size:13,color:v?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:v?"var(--brass-700)":!d||t?"var(--text-body)":"var(--text-muted)",fontWeight:v?600:400},children:c})]},c)})]})]})}function ve({projectId:s,projectName:a,docStatus:i}){const[r,x]=l.useState([]),[g,d]=l.useState(0),[t,h]=re(ue("docs",s),"selected","",pe),[u,p]=l.useState({}),[c,f]=l.useState("preview"),[v,P]=l.useState("tree"),[w,F]=l.useState(""),[S,M]=l.useState(!1),{confirm:K,dialog:U}=oe(),[H,z]=l.useState("loading"),[V,q]=l.useState(0);l.useEffect(()=>{let n=!0;return z("loading"),y.getDocs(s).then(o=>{if(!n)return;const m=o.tree;x(m),d(o.coverage),p({}),f("preview"),z("ready"),h(O(m))}).catch(()=>{n&&(x([]),h(""),z("error"))}),()=>{n=!1}},[s,V]),l.useEffect(()=>{if(!t||t in u)return;let n=!0;return y.getDoc(s,t).then(o=>{n&&p(m=>({...m,[t]:o.content}))}).catch(()=>{n&&p(o=>({...o,[t]:null}))}),()=>{n=!1}},[t,s,u]);const D=!!t&&!(t in u),C=t?u[t]===null:!1,Q=()=>p(n=>{const o={...n};return delete o[t],o}),X=l.useMemo(()=>G(r.filter(n=>n.scored)),[r]),L=l.useMemo(()=>G(r.filter(n=>!n.scored)),[r]),N=u[t]??"",Y=t.includes("/")?t.slice(0,t.lastIndexOf("/")):".",B=r.find(n=>n.cat===Y),Z=t,_=i==="broken"?"err":i==="drift"?"warn":"ok",ee=i==="broken"?"broken":i==="drift"?"drift":"ok";function te(){F(N),f("edit")}function ne(){f("preview")}async function se(){await y.putDoc(s,t,w),p(n=>({...n,[t]:w})),f("preview")}function E(n){h(n),f("preview"),P("viewer")}async function R(){const n=await y.getDocs(s),o=n.tree;x(o),d(n.coverage),o.some(m=>m.files.some(ie=>`${m.cat}/${ie}`===t))||h(O(o))}async function W(){if(!S){M(!0);try{await R()}finally{M(!1)}}}async function ae(){t&&await K({title:`Hapus ${t}?`,message:"Berkas aslinya di disk ikut dihapus — dokumen ini adalah Source of Truth project.",confirmLabel:"Hapus dokumen",run:()=>y.deleteDoc(s,t)})&&(p(n=>{const o={...n};return delete o[t],o}),await R())}return e.jsxs(e.Fragment,{children:[e.jsx(le,{ariaLabel:"Panel Docs",active:v,onActiveChange:n=>P(n),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Files",className:"hn-panel-flex",content:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0,overflow:"auto"},children:[e.jsxs(T,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"12px 14px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsxs("span",{className:"hn-eyebrow",children:["docs · ",a]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(de,{status:ee,size:"sm"}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:S?"loader":"radar",onClick:W,disabled:S,children:S?"…":"Muat ulang"})]})]}),e.jsx("div",{style:{padding:"4px 8px"},children:H==="loading"?e.jsx(b,{kind:"loading",compact:!0,title:"Memuat index…"}):H==="error"?e.jsx(b,{kind:"error",compact:!0,title:"Gagal memuat index docs",hint:a,action:()=>q(n=>n+1)}):r.length===0?e.jsx(b,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada docs",hint:"Belum ada Markdown di repo ini.",action:W,actionLabel:"Muat ulang",actionIcon:"radar"}):e.jsxs(e.Fragment,{children:[X.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path)),L.length>0&&e.jsxs("div",{style:{marginTop:8,paddingTop:8,borderTop:"1px solid var(--border-hair)"},children:[e.jsx("div",{className:"hn-eyebrow",style:{padding:"4px 6px",color:"var(--text-subtle)"},children:"Lainnya (tidak dinilai)"}),L.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path))]})]})})]}),e.jsxs(T,{padding:16,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:12},children:[e.jsx("span",{className:"hn-eyebrow",children:"SoT coverage"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:a})]}),e.jsx(ce,{value:g,showLabel:!0,label:"Kategori ter-index",tone:_})]})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs(T,{padding:0,fill:!0,children:[e.jsxs("div",{style:{flex:"0 0 auto",display:"flex",alignItems:"center",gap:12,padding:"12px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(k,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:Z}),B&&B.scored&&(B.linked?e.jsx($,{tone:"ok",size:"sm",icon:"link",children:"indexed"}):e.jsx($,{tone:"err",size:"sm",icon:"unlink",children:"unlinked"})),e.jsx("span",{style:{flex:1}}),c==="preview"?e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(xe,{href:n=>y.docDownloadUrl(s,t,n),disabled:!t||D||C}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:ae,disabled:!t,children:"Hapus"}),e.jsx(j,{size:"sm",variant:"secondary",leftIcon:"pencil",onClick:te,disabled:!t||D||C,children:"Edit"})]}):e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(j,{size:"sm",variant:"ghost",onClick:ne,children:"Batal"}),e.jsx(j,{size:"sm",leftIcon:"check",onClick:se,children:"Simpan"})]})]}),c==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",style:{padding:"8px 30px 34px",flex:"1 1 auto",minHeight:0,overflow:"auto"},children:t?D?e.jsx(b,{kind:"loading",title:"Memuat dokumen…",hint:t}):C?e.jsx(b,{kind:"error",title:"Gagal memuat dokumen",hint:t,action:Q}):e.jsx(A,{text:N,name:t}):e.jsx(b,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari pohon docs di kiri."})}):e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"1fr 1fr",flex:"1 1 auto",minHeight:0},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",borderRight:"1px solid var(--border-hair)",minHeight:0},children:[e.jsx("div",{style:{padding:"8px 14px",borderBottom:"1px solid var(--border-hair)",background:"var(--bone-100)"},children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{value:w,onChange:n=>F(n.target.value),spellCheck:!1,placeholder:`# Judul dokumen
1
+ import{h as re,u as oe,e as y,j as e,v as le,as as T,ao as de,a as j,f as b,aP as ce,I as k,B as $,ay as xe,aA as A,p as pe,aC as ue}from"./index-gNO91_qw.js";import{R as l}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function J(s){let a={...s,kids:s.kids.map(J)};for(;!a.cat&&a.kids.length===1;){const i=a.kids[0];a={...i,label:a.label+"/"+i.label}}return a}function G(s){const a={path:"",kids:[]};for(const i of s){if(i.cat==="."){a.kids.push({path:".",label:".",cat:i,kids:[]});continue}let r=a;for(const x of i.cat.split("/")){const g=r.path?r.path+"/"+x:x;let d=r.kids.find(t=>t.path===g);d||(d={path:g,label:x,kids:[]},r.kids.push(d)),r=d}r.cat=i}return a.kids.map(J)}function O(s){const a=s.find(i=>i.scored&&i.linked)??s.find(i=>i.scored)??s[0];return a&&a.files[0]?`${a.cat}/${a.files[0]}`:""}function I({node:s,selected:a,onSelect:i,depth:r=0}){var h,u,p;const[x,g]=l.useState(!1),d=((h=s.cat)==null?void 0:h.scored)??!0,t=((u=s.cat)==null?void 0:u.linked)??!0;return e.jsxs("div",{style:r===0?{borderBottom:"1px solid var(--border-hair)"}:void 0,children:[e.jsxs("button",{onClick:()=>g(c=>!c),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"9px 6px",paddingLeft:6+r*12,border:"none",background:"transparent",cursor:"pointer",textAlign:"left"},children:[e.jsx(k,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),e.jsx(k,{name:"folder",size:15,color:d?t?"var(--brass-500)":"var(--clay-500)":"var(--text-subtle)"}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:"var(--text-strong)",fontWeight:500},children:[s.label,"/"]}),e.jsx("span",{style:{flex:1}}),s.cat&&d&&(s.cat.linked?e.jsx(k,{name:"link",size:13,color:"var(--leaf-600)"}):e.jsx(k,{name:"unlink",size:13,color:"var(--clay-500)"}))]}),x&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:1,paddingBottom:4},children:[s.kids.map(c=>e.jsx(I,{node:c,selected:a,onSelect:i,depth:r+1},c.path)),(p=s.cat)==null?void 0:p.files.map(c=>{const f=s.path+"/"+c,v=f===a;return e.jsxs("button",{onClick:()=>i(f),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"6px 8px",paddingLeft:18+r*12,borderRadius:"var(--radius-sm)",border:"none",cursor:"pointer",textAlign:"left",background:v?"var(--brass-100)":"transparent"},children:[e.jsx(k,{name:"file-text",size:13,color:v?"var(--brass-700)":"var(--text-subtle)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:v?"var(--brass-700)":!d||t?"var(--text-body)":"var(--text-muted)",fontWeight:v?600:400},children:c})]},c)})]})]})}function ve({projectId:s,projectName:a,docStatus:i}){const[r,x]=l.useState([]),[g,d]=l.useState(0),[t,h]=re(ue("docs",s),"selected","",pe),[u,p]=l.useState({}),[c,f]=l.useState("preview"),[v,P]=l.useState("tree"),[w,F]=l.useState(""),[S,M]=l.useState(!1),{confirm:K,dialog:U}=oe(),[H,z]=l.useState("loading"),[V,q]=l.useState(0);l.useEffect(()=>{let n=!0;return z("loading"),y.getDocs(s).then(o=>{if(!n)return;const m=o.tree;x(m),d(o.coverage),p({}),f("preview"),z("ready"),h(O(m))}).catch(()=>{n&&(x([]),h(""),z("error"))}),()=>{n=!1}},[s,V]),l.useEffect(()=>{if(!t||t in u)return;let n=!0;return y.getDoc(s,t).then(o=>{n&&p(m=>({...m,[t]:o.content}))}).catch(()=>{n&&p(o=>({...o,[t]:null}))}),()=>{n=!1}},[t,s,u]);const D=!!t&&!(t in u),C=t?u[t]===null:!1,Q=()=>p(n=>{const o={...n};return delete o[t],o}),X=l.useMemo(()=>G(r.filter(n=>n.scored)),[r]),L=l.useMemo(()=>G(r.filter(n=>!n.scored)),[r]),N=u[t]??"",Y=t.includes("/")?t.slice(0,t.lastIndexOf("/")):".",B=r.find(n=>n.cat===Y),Z=t,_=i==="broken"?"err":i==="drift"?"warn":"ok",ee=i==="broken"?"broken":i==="drift"?"drift":"ok";function te(){F(N),f("edit")}function ne(){f("preview")}async function se(){await y.putDoc(s,t,w),p(n=>({...n,[t]:w})),f("preview")}function E(n){h(n),f("preview"),P("viewer")}async function R(){const n=await y.getDocs(s),o=n.tree;x(o),d(n.coverage),o.some(m=>m.files.some(ie=>`${m.cat}/${ie}`===t))||h(O(o))}async function W(){if(!S){M(!0);try{await R()}finally{M(!1)}}}async function ae(){t&&await K({title:`Hapus ${t}?`,message:"Berkas aslinya di disk ikut dihapus — dokumen ini adalah Source of Truth project.",confirmLabel:"Hapus dokumen",run:()=>y.deleteDoc(s,t)})&&(p(n=>{const o={...n};return delete o[t],o}),await R())}return e.jsxs(e.Fragment,{children:[e.jsx(le,{ariaLabel:"Panel Docs",active:v,onActiveChange:n=>P(n),masterWidth:288,className:"hn-workspace-panels",panels:[{id:"tree",label:"Files",className:"hn-panel-flex",content:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0,overflow:"auto"},children:[e.jsxs(T,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"12px 14px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsxs("span",{className:"hn-eyebrow",children:["docs · ",a]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(de,{status:ee,size:"sm"}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:S?"loader":"radar",onClick:W,disabled:S,children:S?"…":"Muat ulang"})]})]}),e.jsx("div",{style:{padding:"4px 8px"},children:H==="loading"?e.jsx(b,{kind:"loading",compact:!0,title:"Memuat index…"}):H==="error"?e.jsx(b,{kind:"error",compact:!0,title:"Gagal memuat index docs",hint:a,action:()=>q(n=>n+1)}):r.length===0?e.jsx(b,{kind:"empty",compact:!0,icon:"folder-open",title:"Belum ada docs",hint:"Belum ada Markdown di repo ini.",action:W,actionLabel:"Muat ulang",actionIcon:"radar"}):e.jsxs(e.Fragment,{children:[X.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path)),L.length>0&&e.jsxs("div",{style:{marginTop:8,paddingTop:8,borderTop:"1px solid var(--border-hair)"},children:[e.jsx("div",{className:"hn-eyebrow",style:{padding:"4px 6px",color:"var(--text-subtle)"},children:"Lainnya (tidak dinilai)"}),L.map(n=>e.jsx(I,{node:n,selected:t,onSelect:E},n.path))]})]})})]}),e.jsxs(T,{padding:16,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:12},children:[e.jsx("span",{className:"hn-eyebrow",children:"SoT coverage"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:a})]}),e.jsx(ce,{value:g,showLabel:!0,label:"Kategori ter-index",tone:_})]})]})},{id:"viewer",label:"Dokumen",className:"hn-panel-flex",content:e.jsxs(T,{padding:0,fill:!0,children:[e.jsxs("div",{style:{flex:"0 0 auto",display:"flex",alignItems:"center",gap:12,padding:"12px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(k,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:Z}),B&&B.scored&&(B.linked?e.jsx($,{tone:"ok",size:"sm",icon:"link",children:"indexed"}):e.jsx($,{tone:"err",size:"sm",icon:"unlink",children:"unlinked"})),e.jsx("span",{style:{flex:1}}),c==="preview"?e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(xe,{href:n=>y.docDownloadUrl(s,t,n),disabled:!t||D||C}),e.jsx(j,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:ae,disabled:!t,children:"Hapus"}),e.jsx(j,{size:"sm",variant:"secondary",leftIcon:"pencil",onClick:te,disabled:!t||D||C,children:"Edit"})]}):e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(j,{size:"sm",variant:"ghost",onClick:ne,children:"Batal"}),e.jsx(j,{size:"sm",leftIcon:"check",onClick:se,children:"Simpan"})]})]}),c==="preview"?e.jsx("div",{"data-testid":"doc-preview-scroll",style:{padding:"8px 30px 34px",flex:"1 1 auto",minHeight:0,overflow:"auto"},children:t?D?e.jsx(b,{kind:"loading",title:"Memuat dokumen…",hint:t}):C?e.jsx(b,{kind:"error",title:"Gagal memuat dokumen",hint:t,action:Q}):e.jsx(A,{text:N,name:t}):e.jsx(b,{kind:"empty",icon:"file-text",title:"Tidak ada dokumen dipilih",hint:"Pilih file dari pohon docs di kiri."})}):e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"1fr 1fr",flex:"1 1 auto",minHeight:0},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",borderRight:"1px solid var(--border-hair)",minHeight:0},children:[e.jsx("div",{style:{padding:"8px 14px",borderBottom:"1px solid var(--border-hair)",background:"var(--bone-100)"},children:e.jsx("span",{className:"hn-eyebrow",children:"Markdown"})}),e.jsx("textarea",{value:w,onChange:n=>F(n.target.value),spellCheck:!1,placeholder:`# Judul dokumen
2
2
 
3
3
  Paragraf pembuka…`,style:{flex:1,width:"100%",boxSizing:"border-box",resize:"none",border:"none",outline:"none",padding:"16px 18px",fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.7,color:"var(--text-body)",background:"var(--surface-card)"}})]}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:0},children:[e.jsx("div",{style:{padding:"8px 14px",borderBottom:"1px solid var(--border-hair)",background:"var(--bone-100)"},children:e.jsx("span",{className:"hn-eyebrow",children:"Preview langsung"})}),e.jsx("div",{style:{flex:1,overflow:"auto",padding:"4px 24px 24px"},children:e.jsx(A,{text:w,name:t})})]})]})]})}]}),U]})}export{ve as DocsWorkspace,G as buildTree,O as firstDoc};