@ngocsangairvds/vsaf 5.8.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -15
- package/package.json +1 -1
- package/packages/cli/dist/adapters/antigravity.d.ts.map +1 -1
- package/packages/cli/dist/adapters/antigravity.js +12 -5
- package/packages/cli/dist/adapters/antigravity.js.map +1 -1
- package/packages/cli/dist/adapters/claude.d.ts.map +1 -1
- package/packages/cli/dist/adapters/claude.js +18 -6
- package/packages/cli/dist/adapters/claude.js.map +1 -1
- package/packages/cli/dist/adapters/codex.d.ts.map +1 -1
- package/packages/cli/dist/adapters/codex.js +13 -5
- package/packages/cli/dist/adapters/codex.js.map +1 -1
- package/packages/cli/dist/adapters/cursor.d.ts.map +1 -1
- package/packages/cli/dist/adapters/cursor.js +22 -6
- package/packages/cli/dist/adapters/cursor.js.map +1 -1
- package/packages/cli/dist/commands/run.js +1 -1
- package/packages/cli/dist/commands/run.js.map +1 -1
- package/packages/cli/dist/index.js +1 -1
- package/packages/cli/dist/index.js.map +1 -1
- package/packages/cli/dist/mcp/server.js +1 -1
- package/packages/cli/dist/mcp/server.js.map +1 -1
- package/packages/core/dist/engine/dag-executor.js +1 -1
- package/packages/core/dist/engine/dag-executor.js.map +1 -1
- package/packages/web/dist/web/browser/chunk-33F7AVPH.js +1 -0
- package/packages/web/dist/web/browser/chunk-FBCNCNPM.js +4 -0
- package/packages/web/dist/web/browser/chunk-UDCOYDXU.js +1 -0
- package/packages/web/dist/web/browser/index.html +1 -1
- package/packages/web/dist/web/browser/{main-NH3DOZDL.js → main-3UCJ3N4F.js} +1 -1
- package/workflows/sdlc/{sdlc-architecture.yaml → architecture.yaml} +1 -1
- package/workflows/sdlc/{sdlc-build-headless.yaml → build-headless.yaml} +1 -1
- package/workflows/sdlc/{sdlc-build.yaml → build.yaml} +1 -1
- package/workflows/sdlc/{sdlc-design.yaml → design.yaml} +1 -1
- package/workflows/sdlc/{sdlc-discovery.yaml → discovery.yaml} +1 -1
- package/workflows/sdlc/{sdlc-feature-complete.yaml → feature-complete.yaml} +1 -1
- package/workflows/sdlc/{sdlc-hotfix-analyze.yaml → hotfix-analyze.yaml} +1 -1
- package/workflows/sdlc/{sdlc-hotfix-implement.yaml → hotfix-implement.yaml} +1 -1
- package/workflows/sdlc/{sdlc-hotfix-prd.yaml → hotfix-prd.yaml} +1 -1
- package/workflows/sdlc/{sdlc-hotfix-review.yaml → hotfix-review.yaml} +1 -1
- package/workflows/sdlc/{sdlc-hotfix-ship.yaml → hotfix-ship.yaml} +1 -1
- package/workflows/sdlc/hotfix-tdd.yaml +1 -1
- package/workflows/sdlc/hotfix.yaml +4 -4
- package/workflows/sdlc/{sdlc-implement.yaml → implement.yaml} +1 -1
- package/workflows/sdlc/{master-sdlc-headless.yaml → master-headless.yaml} +10 -10
- package/workflows/sdlc/{master-sdlc.yaml → master.yaml} +10 -10
- package/workflows/sdlc/{sdlc-prd.yaml → prd.yaml} +1 -1
- package/workflows/sdlc/{sdlc-qa.yaml → qa.yaml} +1 -1
- package/workflows/sdlc/{sdlc-review.yaml → review.yaml} +1 -1
- package/workflows/sdlc/{sdlc-ship.yaml → ship.yaml} +1 -1
- package/workflows/sdlc/{sdlc-srs.yaml → srs.yaml} +1 -1
- package/workflows/sdlc/{sdlc-test-design.yaml → test-design.yaml} +1 -1
- package/workflows/sdlc/{sdlc-testcase.yaml → testcase.yaml} +1 -1
- package/workflows/sdlc/{sdlc-thinking.yaml → thinking.yaml} +1 -1
- package/packages/web/dist/web/browser/chunk-67SQ7ZNG.js +0 -1
- package/packages/web/dist/web/browser/chunk-WNFSSUWZ.js +0 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as S,c as P,e as M,f as O,g as A}from"./chunk-N3FOQ3O5.js";import{Ba as f,Bb as w,La as x,Ma as u,O as d,Oa as C,Pa as v,Qa as s,Ra as n,Sa as o,T as m,Ta as h,U as g,Vb as j,Wb as L,Xa as b,Ya as k,Za as c,ib as i,jb as _,qa as a,qb as y}from"./chunk-4R37VVI4.js";var E=[{path:"",loadComponent:()=>import("./chunk-MCW5ACIZ.js").then(e=>e.DashboardComponent)},{path:"workflows",loadComponent:()=>import("./chunk-GR7SKUVU.js").then(e=>e.WorkflowsComponent)},{path:"workflows/builder",loadComponent:()=>import("./chunk-
|
|
1
|
+
import{a as S,c as P,e as M,f as O,g as A}from"./chunk-N3FOQ3O5.js";import{Ba as f,Bb as w,La as x,Ma as u,O as d,Oa as C,Pa as v,Qa as s,Ra as n,Sa as o,T as m,Ta as h,U as g,Vb as j,Wb as L,Xa as b,Ya as k,Za as c,ib as i,jb as _,qa as a,qb as y}from"./chunk-4R37VVI4.js";var E=[{path:"",loadComponent:()=>import("./chunk-MCW5ACIZ.js").then(e=>e.DashboardComponent)},{path:"workflows",loadComponent:()=>import("./chunk-GR7SKUVU.js").then(e=>e.WorkflowsComponent)},{path:"workflows/builder",loadComponent:()=>import("./chunk-FBCNCNPM.js").then(e=>e.WorkflowBuilderComponent)},{path:"workflows/detail",loadComponent:()=>import("./chunk-6H3AYIT3.js").then(e=>e.WorkflowDetailComponent)},{path:"conversations",loadComponent:()=>import("./chunk-FE2VGLSN.js").then(e=>e.ConversationsComponent)},{path:"conversations/:conversationId",loadComponent:()=>import("./chunk-FE2VGLSN.js").then(e=>e.ConversationsComponent)},{path:"runs/:runId",loadComponent:()=>import("./chunk-UDCOYDXU.js").then(e=>e.RunExecutionComponent)},{path:"settings",loadComponent:()=>import("./chunk-L7B3BT5E.js").then(e=>e.SettingsComponent)}];var I={providers:[w({eventCoalescing:!0}),A(E),j()]};var R=()=>({exact:!0}),T=(e,r)=>r.id;function V(e,r){if(e&1&&(n(0,"option",14),i(1),o()),e&2){let t=r.$implicit,p=c(2);s("value",t.id)("selected",t.id===p.selectedId()),a(),_(t.name)}}function F(e,r){if(e&1){let t=b();n(0,"select",13),k("change",function(z){m(t);let D=c();return g(D.onProjectChange(z))}),C(1,V,2,3,"option",14,T),o()}if(e&2){let t=c();a(),v(t.projects())}}var l=class e{projectService=d(L);projects=this.projectService.projects;selectedId=this.projectService.selectedId;constructor(){this.projectService.load()}onProjectChange(r){let t=r.target.value;!t||t===this.selectedId()||(this.projectService.select(t),document.location.reload())}static \u0275fac=function(t){return new(t||e)};static \u0275cmp=f({type:e,selectors:[["app-root"]],decls:21,vars:3,consts:[[1,"app-shell"],[1,"app-nav"],["routerLink","/",1,"brand-link"],[1,"brand-icon"],[1,"brand-name"],["routerLink","/","routerLinkActive","border-primary text-primary",1,"nav-link",3,"routerLinkActiveOptions"],["routerLink","/workflows","routerLinkActive","border-primary text-primary",1,"nav-link"],["routerLink","/conversations","routerLinkActive","border-primary text-primary",1,"nav-link"],["routerLink","/settings","routerLinkActive","border-primary text-primary",1,"nav-link"],[1,"nav-spacer"],["aria-label","Project","title","Switch project",1,"project-select"],[1,"version-pill"],[1,"app-main"],["aria-label","Project","title","Switch project",1,"project-select",3,"change"],[3,"value","selected"]],template:function(t,p){t&1&&(n(0,"div",0)(1,"nav",1)(2,"a",2)(3,"span",3),i(4,"V"),o(),n(5,"span",4),i(6,"VSAF"),o()(),n(7,"a",5),i(8," Dashboard "),o(),n(9,"a",6),i(10," Workflows "),o(),n(11,"a",7),i(12," Conversations "),o(),n(13,"a",8),i(14," Settings "),o(),n(15,"div",9),x(16,F,3,0,"select",10),n(17,"span",11),i(18,"v0.2.0"),o()()(),n(19,"main",12),h(20,"router-outlet"),o()()),t&2&&(a(7),s("routerLinkActiveOptions",y(2,R)),a(9),u(p.projects().length>1?16:-1))},dependencies:[P,M,O],styles:["[_nghost-%COMP%]{display:block;min-height:100vh;background:#101114;color:#e7e7ea}.app-shell[_ngcontent-%COMP%]{min-height:100vh;background:#101114;color:#e7e7ea}.app-nav[_ngcontent-%COMP%]{display:flex;align-items:center;gap:4px;height:56px;border-bottom:1px solid #2b2d33;background:#17181d;padding:0 16px;box-sizing:border-box}.brand-link[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:9px;margin-right:18px;color:#f4f4f5;text-decoration:none}.brand-link[_ngcontent-%COMP%]:hover{opacity:.82}.brand-icon[_ngcontent-%COMP%]{display:grid;place-items:center;width:30px;height:30px;border-radius:7px;background:#6366f1;color:#fff;font-size:14px;font-weight:800}.brand-name[_ngcontent-%COMP%]{font-size:14px;font-weight:800}.nav-link[_ngcontent-%COMP%]{display:inline-flex;align-items:center;height:56px;border-bottom:2px solid transparent;padding:0 13px;color:#a1a1aa;font-size:14px;font-weight:650;text-decoration:none;box-sizing:border-box}.nav-link[_ngcontent-%COMP%]:hover{color:#f4f4f5}.nav-link.border-primary[_ngcontent-%COMP%], .nav-link.text-primary[_ngcontent-%COMP%]{border-bottom-color:#6366f1;color:#a5b4fc}.nav-spacer[_ngcontent-%COMP%]{margin-left:auto;display:flex;align-items:center;gap:12px}.project-select[_ngcontent-%COMP%]{border:1px solid #2b2d33;border-radius:7px;background:#20222a;color:#e7e7ea;padding:5px 8px;font:inherit;font-size:12px;max-width:220px;cursor:pointer}.project-select[_ngcontent-%COMP%]:focus{outline:none;border-color:#6366f1}.version-pill[_ngcontent-%COMP%]{border:1px solid #2b2d33;border-radius:7px;background:#20222a;color:#a1a1aa;padding:5px 8px;font-size:12px}.app-main[_ngcontent-%COMP%]{min-height:calc(100vh - 56px);overflow:auto;background:#101114}"]})};S(l,I).catch(e=>console.error(e));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: build-headless
|
|
2
2
|
description: 'Sub-flow (Archon-style): Implement in a single loop that runs the tests IN-LOOP and finishes only when green. Toolchain provisioned once (Docker when the host lacks it). Acyclic — no on_fail back-edge.'
|
|
3
3
|
provider: claude
|
|
4
4
|
model: sonnet
|
|
@@ -5,14 +5,14 @@ nodes:
|
|
|
5
5
|
- id: analyze
|
|
6
6
|
description: "Analyze — grill user, GitNexus impact, root cause, blast radius"
|
|
7
7
|
bash: |
|
|
8
|
-
vsaf run sdlc/
|
|
8
|
+
vsaf run sdlc/hotfix-analyze --args $ARGUMENTS
|
|
9
9
|
workspace: false
|
|
10
10
|
timeout: 5400000
|
|
11
11
|
|
|
12
12
|
- id: prd
|
|
13
13
|
description: "PRD — fix requirements, acceptance criteria, scope boundary"
|
|
14
14
|
bash: |
|
|
15
|
-
vsaf run sdlc/
|
|
15
|
+
vsaf run sdlc/hotfix-prd --args $ARGUMENTS
|
|
16
16
|
depends_on: [analyze]
|
|
17
17
|
workspace: false
|
|
18
18
|
timeout: 5400000
|
|
@@ -20,7 +20,7 @@ nodes:
|
|
|
20
20
|
- id: implement
|
|
21
21
|
description: "Implement — TDD (RED → GREEN → REFACTOR), SonarQube-in-loop"
|
|
22
22
|
bash: |
|
|
23
|
-
vsaf run sdlc/
|
|
23
|
+
vsaf run sdlc/hotfix-implement --args $ARGUMENTS
|
|
24
24
|
depends_on: [prd]
|
|
25
25
|
|
|
26
26
|
- id: test-gate
|
|
@@ -40,7 +40,7 @@ nodes:
|
|
|
40
40
|
- id: ship
|
|
41
41
|
description: "Ship — commit, PR on hotfix branch"
|
|
42
42
|
bash: |
|
|
43
|
-
vsaf run sdlc/
|
|
43
|
+
vsaf run sdlc/hotfix-ship --args $ARGUMENTS
|
|
44
44
|
depends_on: [test-gate]
|
|
45
45
|
workspace: false
|
|
46
46
|
timeout: 5400000
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
name: master-
|
|
1
|
+
name: master-headless
|
|
2
2
|
description: Full SDLC pipeline (headless implement, single-workspace) — Discovery → PRD → Architecture → SRS → Test Design → Implement (headless) → Review → Feature Complete → Ship
|
|
3
3
|
nodes:
|
|
4
4
|
- id: discovery
|
|
5
|
-
workflow: sdlc/
|
|
5
|
+
workflow: sdlc/discovery
|
|
6
6
|
- id: prd
|
|
7
|
-
workflow: sdlc/
|
|
7
|
+
workflow: sdlc/prd
|
|
8
8
|
depends_on: [discovery]
|
|
9
9
|
- id: architecture
|
|
10
|
-
workflow: sdlc/
|
|
10
|
+
workflow: sdlc/architecture
|
|
11
11
|
depends_on: [prd]
|
|
12
12
|
- id: srs
|
|
13
|
-
workflow: sdlc/
|
|
13
|
+
workflow: sdlc/srs
|
|
14
14
|
depends_on: [architecture]
|
|
15
15
|
- id: test-design
|
|
16
|
-
workflow: sdlc/
|
|
16
|
+
workflow: sdlc/test-design
|
|
17
17
|
depends_on: [srs]
|
|
18
18
|
- id: implement
|
|
19
|
-
workflow: sdlc/
|
|
19
|
+
workflow: sdlc/build-headless
|
|
20
20
|
depends_on: [test-design]
|
|
21
21
|
- id: review
|
|
22
|
-
workflow: sdlc/
|
|
22
|
+
workflow: sdlc/review
|
|
23
23
|
depends_on: [implement]
|
|
24
24
|
- id: complete
|
|
25
|
-
workflow: sdlc/
|
|
25
|
+
workflow: sdlc/feature-complete
|
|
26
26
|
depends_on: [review]
|
|
27
27
|
- id: ship
|
|
28
|
-
workflow: sdlc/
|
|
28
|
+
workflow: sdlc/ship
|
|
29
29
|
depends_on: [complete]
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
name: master
|
|
1
|
+
name: master
|
|
2
2
|
description: Full SDLC pipeline — Discovery → PRD → Architecture → SRS → Test Design → Implement → Review → Feature Complete → Ship
|
|
3
3
|
nodes:
|
|
4
4
|
- id: discovery
|
|
5
5
|
description: Phase — Discovery
|
|
6
6
|
bash: |
|
|
7
|
-
vsaf run sdlc/
|
|
7
|
+
vsaf run sdlc/discovery --args $ARGUMENTS
|
|
8
8
|
workspace: false
|
|
9
9
|
timeout: 5400000
|
|
10
10
|
- id: prd
|
|
11
11
|
description: Phase — PRD
|
|
12
12
|
bash: |
|
|
13
|
-
vsaf run sdlc/
|
|
13
|
+
vsaf run sdlc/prd --args $ARGUMENTS
|
|
14
14
|
workspace: false
|
|
15
15
|
timeout: 5400000
|
|
16
16
|
depends_on:
|
|
@@ -18,7 +18,7 @@ nodes:
|
|
|
18
18
|
- id: architecture
|
|
19
19
|
description: Phase — Architecture
|
|
20
20
|
bash: |
|
|
21
|
-
vsaf run sdlc/
|
|
21
|
+
vsaf run sdlc/architecture --args $ARGUMENTS
|
|
22
22
|
workspace: false
|
|
23
23
|
timeout: 5400000
|
|
24
24
|
depends_on:
|
|
@@ -26,7 +26,7 @@ nodes:
|
|
|
26
26
|
- id: srs
|
|
27
27
|
description: Phase — SRS
|
|
28
28
|
bash: |
|
|
29
|
-
vsaf run sdlc/
|
|
29
|
+
vsaf run sdlc/srs --args $ARGUMENTS
|
|
30
30
|
workspace: false
|
|
31
31
|
timeout: 5400000
|
|
32
32
|
depends_on:
|
|
@@ -34,7 +34,7 @@ nodes:
|
|
|
34
34
|
- id: test-design
|
|
35
35
|
description: Phase — Test Design
|
|
36
36
|
bash: |
|
|
37
|
-
vsaf run sdlc/
|
|
37
|
+
vsaf run sdlc/test-design --args $ARGUMENTS
|
|
38
38
|
workspace: false
|
|
39
39
|
timeout: 5400000
|
|
40
40
|
depends_on:
|
|
@@ -42,7 +42,7 @@ nodes:
|
|
|
42
42
|
- id: implement
|
|
43
43
|
description: Phase — Implement
|
|
44
44
|
bash: |
|
|
45
|
-
vsaf run sdlc/
|
|
45
|
+
vsaf run sdlc/implement --args $ARGUMENTS
|
|
46
46
|
workspace: false
|
|
47
47
|
timeout: 5400000
|
|
48
48
|
depends_on:
|
|
@@ -50,7 +50,7 @@ nodes:
|
|
|
50
50
|
- id: review
|
|
51
51
|
description: Phase — Review
|
|
52
52
|
bash: |
|
|
53
|
-
vsaf run sdlc/
|
|
53
|
+
vsaf run sdlc/review --args $ARGUMENTS
|
|
54
54
|
workspace: false
|
|
55
55
|
timeout: 5400000
|
|
56
56
|
depends_on:
|
|
@@ -58,7 +58,7 @@ nodes:
|
|
|
58
58
|
- id: complete
|
|
59
59
|
description: Phase — Feature Complete
|
|
60
60
|
bash: |
|
|
61
|
-
vsaf run sdlc/
|
|
61
|
+
vsaf run sdlc/feature-complete --args $ARGUMENTS
|
|
62
62
|
workspace: false
|
|
63
63
|
timeout: 5400000
|
|
64
64
|
depends_on:
|
|
@@ -66,7 +66,7 @@ nodes:
|
|
|
66
66
|
- id: ship
|
|
67
67
|
description: Phase — Ship
|
|
68
68
|
bash: |
|
|
69
|
-
vsaf run sdlc/
|
|
69
|
+
vsaf run sdlc/ship --args $ARGUMENTS
|
|
70
70
|
workspace: false
|
|
71
71
|
timeout: 5400000
|
|
72
72
|
depends_on:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as we,e as Ie}from"./chunk-N3FOQ3O5.js";import{a as Se,b as De,e as ke,j as Ne,k as B}from"./chunk-7ELOO4IC.js";import{$ as z,Ba as F,Fa as ee,J as de,Ka as D,Kb as xe,La as C,Lb as ye,Ma as E,Mb as Ce,Na as pe,O as S,Oa as P,Pa as H,Pb as Ee,Qa as g,Qb as A,Ra as d,Sa as o,T as M,Ta as k,U as T,V as G,Wb as Me,Xa as R,Ya as h,Za as m,a as oe,aa as ue,b as se,bb as ce,cb as me,db as ge,ea as le,f as ae,gb as K,ib as l,jb as w,kb as q,lb as j,mb as he,nb as fe,oa as Z,ob as be,qa as a,sb as ve,tb as _e}from"./chunk-4R37VVI4.js";var X=class i{zone=S(ue);projectService=S(Me);connect(t){return new ae(e=>{let n=this.projectService.currentId,r=n?`?project=${encodeURIComponent(n)}`:"",s=new EventSource(`/api/runs/${t}/events${r}`),_=["node:start","node:complete","node:skip","node:fail","run:complete","run:state","run:pause","run:cancel"];for(let p of _)s.addEventListener(p,u=>{this.zone.run(()=>{e.next({type:p,data:JSON.parse(u.data)})})});return s.onerror=()=>{this.zone.run(()=>{e.complete()}),s.close()},()=>{s.close()}})}static \u0275fac=function(e){return new(e||i)};static \u0275prov=de({token:i,factory:i.\u0275fac,providedIn:"root"})};var qe=new Set(["completed","failed","cancelled"]);function ne(i){return i!==void 0&&qe.has(i)}function Te(i,t=new Date().toISOString()){ne(i.status)&&!i.completedAt&&(i.completedAt=t)}var Be="Approval required",Xe="Run paused \u2014 input required to continue.";function W(i){return`${i.nodeId}\0${i.iteration??""}\0${i.message}`}function Re(i){let t=Oe(i);if(t)return t;let e=i.approval;if(e&&typeof e=="object")return Oe(e)}function Oe(i){let t=V(i.approvalNodeId)??V(i.nodeId);if(!t)return;let e=V(i.approvalMessage)??V(i.message),n=V(i.approvalType)??V(i.type),r=i.iteration;return{nodeId:t,message:e||Be,type:n==="interactive_loop"?"interactive_loop":"approval",iteration:typeof r=="number"?r:void 0}}function V(i){return typeof i=="string"&&i!==""?i:void 0}var Y=class{current;state="hidden";error;answeredKey;pauseReceived(t){this.current=Re(t)??Ge(),this.state="ready",this.error=void 0}runStateChanged(t,e){if(t!=="paused"){this.current=void 0,this.state="hidden",this.error=void 0,this.answeredKey=void 0;return}if(this.state==="submitting")return;let n=e?Re(e):void 0,r=n?W(n):void 0;r!==void 0&&r===this.answeredKey||this.current&&r!==void 0&&r===W(this.current)||this.current&&n===void 0||(this.current=n??Ge(),this.state="ready",this.error=void 0)}submitStarted(){this.state!=="hidden"&&(this.state="submitting",this.error=void 0)}submitFailed(t){this.state!=="hidden"&&(this.state="error",this.error=t)}submitSucceeded(){this.current&&(this.answeredKey=W(this.current)),this.current=void 0,this.state="hidden",this.error=void 0}visible(){return this.state!=="hidden"}phase(){return this.state}request(){return this.current}errorMessage(){return this.error}submitAction(){return this.current?.type==="interactive_loop"?"resume":"approve"}};function Ge(){return{nodeId:"",message:Xe,type:"approval"}}function Fe(i,t,e=new Date().toISOString()){let n=`gate:${W(t)}`;return i.some(r=>r.key===n)?i:[...i,{key:n,role:"gate",text:t.message,at:e,nodeId:t.nodeId,iteration:t.iteration}]}function ie(i,t,e,n=new Date().toISOString()){return[...i,{key:`user:${i.length}:${n}`,role:"user",kind:t,text:Ye(t,e),at:n}]}function Ye(i,t){let e=t.trim();switch(i){case"answer":return e;case"approve":return e?`Approved: ${e}`:"Approved";case"reject":return e?`Rejected: ${e}`:"Rejected"}}function Ae(i){return Ue(i).split(/`([^`]*)`/).map((n,r)=>r%2===1?`<code>${n}</code>`:n.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>")).join("").replace(/\n/g,"<br>")}function Ue(i){return i.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Ve(i){let t=new Map(i.map(c=>[c.key,c])),e=new Map,n=new Set,r=c=>{let b=e.get(c);if(b!==void 0)return b;if(n.has(c))return 0;n.add(c);let N=(t.get(c)?.dependsOn??[]).filter(y=>t.has(y)),x=N.length===0?0:Math.max(...N.map(r))+1;return n.delete(c),e.set(c,x),x};for(let c of i)r(c.key);let s=new Map;for(let c of i){let b=e.get(c.key);(s.get(b)??s.set(b,[]).get(b)).push(c.key)}let _=196,p=84,u=[...s.keys()].sort((c,b)=>c-b),f=new Map;for(let c of u){let b=s.get(c);if(c===0){b.forEach((x,y)=>f.set(x,y));continue}let N=x=>{let y=(t.get(x)?.dependsOn??[]).filter(L=>f.has(L));return y.length===0?f.get(x)??0:y.reduce((L,ze)=>L+f.get(ze),0)/y.length};b.sort((x,y)=>N(x)-N(y)),b.forEach((x,y)=>f.set(x,y))}let I=Math.max(1,...u.map(c=>s.get(c).length))*_,O=new Map;for(let c of u){let b=s.get(c),N=b.length*_,x=(I-N)/2;b.forEach((y,L)=>O.set(y,{x:x+L*_,y:c*p}))}let We=((u.length?u[u.length-1]:0)+1)*p;return{positions:O,layerOf:e,width:I,height:We}}var Je=["host"];function Ze(i,t){if(i&1&&(G(),k(0,"path",9)),i&2){let e=t.$implicit;D("d",e)}}function et(i,t){if(i&1&&(G(),d(0,"text",16),l(1),o()),i&2){let e=m().$implicit,n=m();D("x",n.NODE_W-12)("y",n.NODE_H/2+5),a(),j("",e.progress.done,"/",e.progress.total)}}function tt(i,t){if(i&1&&(G(),d(0,"text",17),l(1,"\u29C9"),o()),i&2){let e=m(2);D("x",e.NODE_W-12)("y",14)}}function nt(i,t){if(i&1){let e=R();G(),d(0,"g",10),h("click",function(){let r=M(e).$implicit,s=m();return T(s.nodeClick.emit(r.key))}),k(1,"rect",11),d(2,"text",12),l(3),o(),d(4,"text",13),l(5),o(),ee(6,et,2,4,"text",14)(7,tt,2,2,"text",15),o()}if(i&2){let e=t.$implicit,n=m();D("transform","translate("+e.x+","+e.y+")"),a(),K("dag-pulse",e.status==="running"),D("width",n.NODE_W)("height",n.NODE_H)("fill",n.fillFor(e.status))("stroke",n.strokeFor(e.status)),a(),D("y",n.NODE_H/2+5)("fill",n.strokeFor(e.status)),a(),w(n.icon(e.status)),a(),D("y",n.NODE_H/2+5),a(),w(n.clip(e.label)),a(),g("ngIf",e.progress),a(),g("ngIf",e.isGroup)}}var $=class i{NODE_W=168;NODE_H=44;nodes=[];edges=[];width=0;height=0;nodeClick=new z;hostRef;scale=1;panX=16;panY=40;dragging=!1;lastX=0;lastY=0;get edgePaths(){let t=new Map(this.nodes.map(n=>[n.key,n])),e=[];for(let n of this.edges){let r=t.get(n.from),s=t.get(n.to);if(!r||!s)continue;let _=r.x+168/2,p=r.y+44,u=s.x+168/2,f=s.y,v=(p+f)/2;e.push(`M${_} ${p} C${_} ${v}, ${u} ${v}, ${u} ${f}`)}return e}onWheel(t){t.preventDefault(),this.zoomBy(t.deltaY<0?1.1:.9)}zoomBy(t,e){e?.stopPropagation(),this.scale=Math.min(2.5,Math.max(.2,this.scale*t))}onDown(t){this.dragging=!0,this.lastX=t.clientX,this.lastY=t.clientY}onMove(t){this.dragging&&(this.panX+=t.clientX-this.lastX,this.panY+=t.clientY-this.lastY,this.lastX=t.clientX,this.lastY=t.clientY)}onUp(){this.dragging=!1}fit(){if(!this.width||!this.height){this.scale=1,this.panX=16,this.panY=40;return}let t=this.hostRef?.nativeElement,e=t?.clientWidth??600,n=t?.clientHeight??400;this.scale=Math.min(2,Math.max(.2,Math.min((e-32)/this.width,(n-48)/this.height))),this.panX=Math.max(16,(e-this.width*this.scale)/2),this.panY=44}clip(t){return t.length>20?t.slice(0,19)+"\u2026":t}icon(t){return{completed:"\u2713",running:"\u25CF",failed:"\u2717",skipped:"\u2298"}[t]??"\u25CB"}fillFor(t){return{completed:"rgba(34,197,94,.14)",running:"rgba(59,130,246,.16)",failed:"rgba(239,68,68,.14)"}[t]??"rgba(30,41,59,.9)"}strokeFor(t){return{completed:"#22c55e",running:"#3b82f6",failed:"#ef4444",skipped:"#64748b"}[t]??"#475569"}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=F({type:i,selectors:[["app-dag-graph"]],viewQuery:function(e,n){if(e&1&&ce(Je,5),e&2){let r;me(r=ge())&&(n.hostRef=r.first)}},inputs:{nodes:"nodes",edges:"edges",width:"width",height:"height"},outputs:{nodeClick:"nodeClick"},decls:16,vars:7,consts:[["host",""],[1,"relative","w-full","h-full","overflow-hidden","select-none","bg-slate-950/40",3,"wheel","mousedown","mousemove","mouseup","mouseleave"],[1,"absolute","top-2","left-2","z-10","flex","gap-1","items-center"],["type","button",1,"dag-btn",3,"click"],[1,"text-xs","text-slate-400","w-10","text-center","font-mono"],["type","button",1,"dag-btn","px-2","w-auto",3,"click"],[1,"absolute","inset-0","w-full","h-full"],["fill","none","stroke","#475569","stroke-width","2","opacity","0.8",4,"ngFor","ngForOf"],["class","cursor-pointer",3,"click",4,"ngFor","ngForOf"],["fill","none","stroke","#475569","stroke-width","2","opacity","0.8"],[1,"cursor-pointer",3,"click"],["rx","9","stroke-width","2"],["x","16","font-size","15"],["x","34","font-size","13","fill","#e2e8f0"],["text-anchor","end","font-size","10","fill","#94a3b8",4,"ngIf"],["text-anchor","end","font-size","11","fill","#94a3b8",4,"ngIf"],["text-anchor","end","font-size","10","fill","#94a3b8"],["text-anchor","end","font-size","11","fill","#94a3b8"]],template:function(e,n){e&1&&(d(0,"div",1,0),h("wheel",function(s){return n.onWheel(s)})("mousedown",function(s){return n.onDown(s)})("mousemove",function(s){return n.onMove(s)})("mouseup",function(){return n.onUp()})("mouseleave",function(){return n.onUp()}),d(2,"div",2)(3,"button",3),h("click",function(s){return n.zoomBy(.8,s)}),l(4,"\u2212"),o(),d(5,"span",4),l(6),ve(7,"number"),o(),d(8,"button",3),h("click",function(s){return n.zoomBy(1.25,s)}),l(9,"+"),o(),d(10,"button",5),h("click",function(){return n.fit()}),l(11,"fit"),o()(),G(),d(12,"svg",6)(13,"g"),ee(14,Ze,1,1,"path",7)(15,nt,8,14,"g",8),o()()()),e&2&&(a(6),q("",_e(7,4,n.scale*100,"1.0-0"),"%"),a(7),D("transform","translate("+n.panX+","+n.panY+") scale("+n.scale+")"),a(),g("ngForOf",n.edgePaths),a(),g("ngForOf",n.nodes))},dependencies:[A,ye,Ce,Ee],styles:[".dag-btn[_ngcontent-%COMP%]{width:24px;height:24px;border:1px solid #334155;border-radius:6px;background:#1e293b;color:#94a3b8;font-size:13px;line-height:1}.dag-btn[_ngcontent-%COMP%]:hover{color:#e2e8f0}.dag-pulse[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_dagpulse 1.3s ease-in-out infinite}@keyframes _ngcontent-%COMP%_dagpulse{0%,to{opacity:1}50%{opacity:.45}}"]})};function U(i,t=""){let e=t===""?"":t+".",n=i.filter(u=>t===""||u.id===t||u.id.startsWith(e)),r=new Map(i.map(u=>[u.id,u])),s=new Map;for(let u of n){let f=t===""?u.id:u.id.slice(e.length),v=f.split(".")[0];if(!v)continue;let I=s.get(v);I||(I={key:e+v,label:v,leafIds:[],deeper:!1},s.set(v,I)),I.leafIds.push(u.id),f.includes(".")&&(I.deeper=!0)}let _=u=>{if(t!==""&&u!==t&&!u.startsWith(e))return;let v=(t===""?u:u.slice(e.length)).split(".")[0];return s.has(v)?e+v:void 0},p=[];for(let u of s.values()){let f=new Set;for(let v of u.leafIds)for(let I of r.get(v)?.dependsOn??[]){let O=_(I);O&&O!==u.key&&f.add(O)}p.push({key:u.key,label:u.label,isGroup:u.deeper,leafIds:u.leafIds,dependsOn:[...f]})}return p}var Pe=new Set(["completed","skipped"]);function He(i,t){let e=i.map(t);return e.some(n=>n==="failed")?"failed":e.some(n=>n==="running")?"running":e.length>0&&e.every(n=>n==="skipped")?"skipped":e.length>0&&e.every(n=>Pe.has(n))?"completed":e.some(n=>n==="completed")?"running":"pending"}function Ke(i,t){let e=i.map(t);return{done:e.filter(n=>Pe.has(n)).length,total:e.length}}function Q(i,t,e=""){let n=U(i,e),r=Ve(n.map(p=>({key:p.key,dependsOn:p.dependsOn}))),s=n.map(p=>{let u=r.positions.get(p.key)??{x:0,y:0};return{key:p.key,label:p.label,isGroup:p.isGroup,status:p.isGroup?He(p.leafIds,t):t(p.leafIds[0]),progress:p.isGroup?Ke(p.leafIds,t):void 0,x:u.x,y:u.y}}),_=[];for(let p of n)for(let u of p.dependsOn)_.push({from:u,to:p.key});return{vms:s,edges:_,width:r.width,height:r.height}}function it(i,t){i&1&&(d(0,"span"),l(1," \u203A "),o())}function rt(i,t){if(i&1){let e=R();d(0,"button",10),h("click",function(){let r=M(e).$implicit,s=m();return T(s.goTo(r))}),l(1),o(),C(2,it,2,0,"span")}if(i&2){let e=t.$implicit,n=t.$index,r=t.$count,s=m();a(),w(s.label(e)),a(),E(n!==r-1?2:-1)}}function ot(i,t){i&1&&(d(0,"div",11),l(1,"\u0110ang t\u1EA3i output\u2026"),o())}function st(i,t){if(i&1&&(d(0,"div",12),l(1),o()),i&2){let e=m(2);a(),w(e.leafError)}}function at(i,t){if(i&1&&(d(0,"pre",13),l(1),o()),i&2){let e=m(3);a(),w(e.leafData==null?null:e.leafData.error)}}function dt(i,t){if(i&1&&(d(0,"pre",14),l(1),o()),i&2){let e=m(3);a(),w(e.leafData==null?null:e.leafData.output)}}function ut(i,t){i&1&&(d(0,"div",15),l(1,"Kh\xF4ng c\xF3 output"),o())}function lt(i,t){if(i&1&&(C(0,at,2,1,"pre",13),C(1,dt,2,1,"pre",14)(2,ut,2,0,"div",15)),i&2){let e=m(2);E(e.leafData!=null&&e.leafData.error?0:-1),a(),E(e.leafData!=null&&e.leafData.output?1:e.leafData!=null&&e.leafData.error?-1:2)}}function pt(i,t){if(i&1&&(d(0,"div",8),C(1,ot,2,0,"div",11)(2,st,2,1,"div",12)(3,lt,3,2),o()),i&2){let e,n=m();a(),E((e=n.leafPhase)==="loading"?1:e==="error"?2:e==="loaded"?3:-1)}}function ct(i,t){if(i&1){let e=R();d(0,"app-dag-graph",16),h("nodeClick",function(r){M(e);let s=m();return T(s.onSubClick(r))}),o()}if(i&2){let e=m();g("nodes",e.subNodes)("edges",e.subEdges)("width",e.subWidth)("height",e.subHeight)}}var J=class i{api=S(B);runId="";nodes=[];statusOf=()=>"pending";rootKey="";close=new z;breadcrumb=[];isLeaf=!1;subNodes=[];subEdges=[];subWidth=0;subHeight=0;leafPhase="loading";leafData;leafError="";ngOnChanges(t){if(t.rootKey){this.breadcrumb=[],this.goTo(this.rootKey);return}(t.nodes||t.statusOf)&&!this.isLeaf&&this.breadcrumb.length&&this.buildSubView(this.breadcrumb[this.breadcrumb.length-1])}goTo(t){let e=this.breadcrumb.indexOf(t);this.breadcrumb=e>=0?this.breadcrumb.slice(0,e+1):[...this.breadcrumb,t];let n=U(this.nodes,t);if(this.isLeaf=n.length===0,this.isLeaf){this.loadLeaf(t);return}this.buildSubView(t)}buildSubView(t){let e=Q(this.nodes,this.statusOf,t);this.subNodes=e.vms,this.subEdges=e.edges,this.subWidth=e.width,this.subHeight=e.height}onSubClick(t){this.goTo(t)}loadLeaf(t){this.leafPhase="loading",this.api.getNodeOutput(this.runId,t).subscribe({next:e=>{this.leafData={output:e.output,error:e.error},this.leafPhase="loaded"},error:e=>{this.leafError=e?.error?.error??"Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c output.",this.leafPhase="error"}})}label(t){return t.split(".").pop()??t}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=F({type:i,selectors:[["app-node-inspector"]],inputs:{runId:"runId",nodes:"nodes",statusOf:"statusOf",rootKey:"rootKey"},outputs:{close:"close"},features:[le],decls:13,vars:1,consts:[[1,"absolute","inset-0","z-20","flex"],[1,"absolute","inset-0","bg-black/40",3,"click"],[1,"relative","m-3","flex-1","max-w-[78%]","bg-slate-900","border","border-slate-700","rounded-xl","shadow-2xl","flex","flex-col","overflow-hidden"],[1,"flex","items-center","gap-2","px-4","py-2.5","border-b","border-slate-800","text-sm"],[1,"text-slate-500"],[1,"flex-1"],["type","button",1,"text-slate-400","hover:text-slate-100",3,"click"],[1,"flex-1","min-h-0","relative"],[1,"absolute","inset-0","overflow-auto","p-4","text-xs"],[3,"nodes","edges","width","height"],["type","button",1,"hover:text-slate-200",3,"click"],[1,"text-slate-500","animate-pulse"],[1,"text-red-400"],[1,"font-mono","text-red-300","bg-red-500/10","border","border-red-500/30","rounded","p-3","mb-2","whitespace-pre-wrap","break-words"],[1,"font-mono","text-slate-300","bg-slate-950","border","border-slate-800","rounded","p-3","whitespace-pre-wrap","break-words"],[1,"text-slate-500","italic"],[3,"nodeClick","nodes","edges","width","height"]],template:function(e,n){e&1&&(d(0,"div",0)(1,"div",1),h("click",function(){return n.close.emit()}),o(),d(2,"div",2)(3,"div",3)(4,"span",4),P(5,rt,3,2,null,null,pe),o(),k(7,"span",5),d(8,"button",6),h("click",function(){return n.close.emit()}),l(9,"\u2715"),o()(),d(10,"div",7),C(11,pt,4,1,"div",8)(12,ct,1,4,"app-dag-graph",9),o()()()),e&2&&(a(5),H(n.breadcrumb),a(6),E(n.isLeaf?11:12))},dependencies:[A,$],encapsulation:2})};var mt=(i,t)=>t.id,gt=(i,t)=>t.key;function ht(i,t){if(i&1&&(d(0,"span",6),l(1),o()),i&2){let e=m();g("ngClass",e.statusClass(e.run.status)),a(),j(" ",e.statusIcon(e.run.status)," ",e.run.status," ")}}function ft(i,t){i&1&&(d(0,"div",10),l(1,"Kh\xF4ng d\u1EF1ng \u0111\u01B0\u1EE3c s\u01A1 \u0111\u1ED3 ph\u1EE5 thu\u1ED9c \u2014 hi\u1EC3n th\u1ECB theo th\u1EE9 t\u1EF1 ch\u1EA1y."),o())}function bt(i,t){if(i&1){let e=R();d(0,"app-node-inspector",23),h("close",function(){M(e);let r=m();return T(r.closeInspector())}),o()}if(i&2){let e=m();g("runId",e.run.runId)("nodes",e.dagInputNodes)("statusOf",e.statusOf)("rootKey",e.inspectorKey)}}function vt(i,t){if(i&1&&(d(0,"div",24)(1,"div",25),k(2,"div",26),o()()),i&2){let e=t.$implicit,n=m();K("justify-end",e.role==="user"),a(),g("ngClass",e.role==="user"?"bg-indigo-500/15 text-indigo-100":"bg-slate-800 text-slate-200"),a(),g("innerHTML",n.render(e.content),Z)}}function _t(i,t){i&1&&(d(0,"div",16),l(1,"\u2014 phi\xEAn hi\u1EC7n t\u1EA1i \u2014"),o())}function xt(i,t){if(i&1&&(d(0,"div",27),l(1),o()),i&2){let e=m().$implicit;a(),j(" \u23F8 ",e.nodeId||"gate","",e.iteration!==void 0?" \xB7 iteration "+e.iteration:""," ")}}function yt(i,t){if(i&1&&(d(0,"div",24)(1,"div",25),C(2,xt,2,2,"div",27),k(3,"div",26),o()()),i&2){let e=t.$implicit,n=m();K("justify-end",e.role==="user"),a(),g("ngClass",e.role==="user"?"bg-indigo-500/15 text-indigo-100":"bg-slate-800 text-slate-200"),a(),E(e.role==="gate"?2:-1),a(),g("innerHTML",n.render(e.text),Z)}}function Ct(i,t){if(i&1&&(d(0,"div",19),l(1),o()),i&2){let e=m();a(),w(e.gate.errorMessage())}}var je=class i{route=S(we);api=S(B);sse=S(X);run;gate=new Y;feed=[];messages=[];draft="";runId="";sseSub;timerInterval;focusAnswerOnShow=!1;dagNodes=[];dagEdges=[];dagWidth=0;dagHeight=0;dagInputNodes=[];statusMap=new Map;ngOnInit(){this.runId=this.route.snapshot.paramMap.get("runId"),this.focusAnswerOnShow=this.route.snapshot.fragment==="answer",this.api.getRun(this.runId).subscribe(t=>{this.run=t,t.conversationId&&this.api.getConversationMessages(t.conversationId).subscribe({next:e=>{this.messages=e.messages},error:()=>{this.messages=[]}}),this.rebuildDag(),this.stopTimerIfFinished(),this.syncGateFromRun()}),this.sseSub=this.sse.connect(this.runId).subscribe(t=>{this.handleSseEvent(t)}),this.timerInterval=setInterval(()=>{},1e3)}ngOnDestroy(){this.sseSub?.unsubscribe(),this.timerInterval&&clearInterval(this.timerInterval)}inspectorKey=null;onNodeClick(t){this.inspectorKey=t}closeInspector(){this.inspectorKey=null}hierInput(){let t=this.run?.graph?.nodes;if(t&&t.length)return t.map(n=>({id:n.id,dependsOn:n.dependsOn}));let e=this.run?Object.keys(this.run.nodes):[];return e.map((n,r)=>({id:n,dependsOn:r===0?[]:[e[r-1]]}))}statusOf=t=>this.statusMap.get(t)??"pending";syncStatusMap(){if(this.run)for(let[t,e]of Object.entries(this.run.nodes))this.statusMap.has(t)||this.statusMap.set(t,e.status)}rebuildDag(){if(!this.run)return;this.syncStatusMap(),this.dagInputNodes=this.hierInput();let t=Q(this.dagInputNodes,this.statusOf,"");this.dagNodes=t.vms,this.dagEdges=t.edges,this.dagWidth=t.width,this.dagHeight=t.height}handleSseEvent(t){let e=t.data,n=e.nodeId;switch(t.type){case"run:state":{let r=e;this.run=se(oe({},r),{graph:r.graph??this.run?.graph,conversationId:r.conversationId??this.run?.conversationId}),this.rebuildDag(),this.stopTimerIfFinished(),this.syncGateFromRun();break}case"run:pause":this.run&&(this.run.status="paused"),this.gate.pauseReceived(e),this.noteGateInFeed(),this.maybeFocusAnswer();break;case"run:cancel":this.run&&(this.run.status="cancelled"),this.gate.runStateChanged("cancelled"),this.stopTimerIfFinished();break;case"node:start":this.updateNodeStatus(n,"running",void 0,{provider:e.provider,model:e.model});break;case"node:complete":this.updateNodeStatus(n,"completed",e.durationMs);break;case"node:skip":this.updateNodeStatus(n,"skipped");break;case"node:fail":this.updateNodeStatus(n,"failed");break;case"run:complete":this.run&&(this.run.status=e.success?"completed":"failed",this.gate.runStateChanged(this.run.status)),this.stopTimerIfFinished();break}}updateNodeStatus(t,e,n,r){this.statusMap.set(t,e),this.rebuildDag()}syncGateFromRun(){this.run&&(this.gate.runStateChanged(this.run.status,this.run),this.noteGateInFeed(),this.maybeFocusAnswer())}noteGateInFeed(){let t=this.gate.request();this.gate.visible()&&t&&(this.feed=Fe(this.feed,t))}sendAnswer(){if(!this.gate.visible()||this.gate.phase()==="submitting")return;let t=this.draft.trim(),e=this.gate.submitAction();if(e==="resume"&&!t)return;this.gate.submitStarted(),(e==="resume"?this.api.resumeRun(this.runId,t):this.api.approveRun(this.runId,t||void 0)).subscribe({next:()=>{this.feed=ie(this.feed,e==="resume"?"answer":"approve",t),this.draft="",this.gate.submitSucceeded()},error:r=>this.gate.submitFailed(r?.error?.error??"Failed to send the answer.")})}rejectGate(){if(!this.gate.visible()||this.gate.phase()==="submitting")return;let t=prompt("Rejection reason","Rejected by operator");t!==null&&(this.gate.submitStarted(),this.api.rejectRun(this.runId,t||void 0).subscribe({next:()=>{this.feed=ie(this.feed,"reject",t),this.gate.submitSucceeded()},error:e=>this.gate.submitFailed(e?.error?.error??"Failed to reject the run.")}))}render(t){return Ae(t)}maybeFocusAnswer(){!this.focusAnswerOnShow||!this.gate.visible()||(this.focusAnswerOnShow=!1,setTimeout(()=>{document.getElementById("gate-answer-panel")?.scrollIntoView({behavior:"smooth",block:"center"}),document.getElementById("gate-answer-input")?.focus()}))}stopTimerIfFinished(){!this.run||!ne(this.run.status)||(Te(this.run),this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=void 0))}statusClass(t){switch(t){case"completed":return"bg-green-500/10 text-green-400";case"failed":return"bg-red-500/10 text-red-400";case"running":return"bg-blue-500/10 text-blue-400";default:return"bg-slate-700 text-slate-400"}}statusIcon(t){switch(t){case"completed":return"\u2713";case"failed":return"\u2717";case"running":return"\u25CF";default:return"\u25CB"}}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=F({type:i,selectors:[["app-run-execution"]],decls:35,vars:17,consts:[[1,"flex","flex-col","h-[calc(100vh-6rem)]"],[1,"flex","items-center","mb-3","gap-2","text-sm","shrink-0"],["routerLink","/",1,"text-slate-500","hover:text-slate-300"],[1,"text-slate-600"],[1,"text-slate-300"],[1,"font-mono","text-slate-100"],[1,"text-xs","px-2","py-0.5","rounded","ml-2",3,"ngClass"],[1,"flex-1","flex","min-h-0","gap-3"],[1,"flex-[1.6]","min-w-0","border","border-slate-800","rounded-lg","overflow-hidden","relative"],[3,"nodeClick","nodes","edges","width","height"],[1,"absolute","bottom-2","left-2","text-[10px]","text-slate-500"],[3,"runId","nodes","statusOf","rootKey"],[1,"flex-1","min-w-0","flex","flex-col","border","border-slate-800","rounded-lg","overflow-hidden"],[1,"px-3","py-2","border-b","border-slate-800","text-sm","text-slate-200","shrink-0"],[1,"flex-1","overflow-auto","p-3","space-y-2"],[1,"flex",3,"justify-end"],[1,"text-[10px]","text-slate-600","text-center"],["id","gate-answer-panel",1,"border-t","border-slate-800","p-3","shrink-0","bg-slate-900/40"],["id","gate-answer-input","rows","2",1,"w-full","rounded","border","border-slate-700","bg-slate-950","p-2","text-sm","text-slate-100","focus:border-amber-500","focus:outline-none",3,"ngModelChange","ngModel","disabled","placeholder"],[1,"text-xs","text-red-400","mt-1"],[1,"flex","gap-2","mt-2"],["type","button",1,"rounded","bg-amber-500","px-3","py-1.5","text-sm","font-semibold","text-slate-950","hover:bg-amber-400","disabled:opacity-40","disabled:cursor-not-allowed",3,"click","disabled"],["type","button",1,"rounded","border","border-red-500/50","px-3","py-1.5","text-sm","text-red-300","hover:bg-red-500/10","disabled:opacity-40",3,"click","disabled"],[3,"close","runId","nodes","statusOf","rootKey"],[1,"flex"],[1,"max-w-[90%]","rounded-lg","px-3","py-2","text-sm",3,"ngClass"],[3,"innerHTML"],[1,"text-[10px]","uppercase","tracking-wide","text-amber-400","mb-1"]],template:function(e,n){e&1&&(d(0,"div",0)(1,"div",1)(2,"a",2),l(3,"Dashboard"),o(),d(4,"span",3),l(5,"\u203A"),o(),d(6,"span",4),l(7),o(),d(8,"span",3),l(9,"\u203A"),o(),d(10,"span",5),l(11),o(),C(12,ht,2,3,"span",6),o(),d(13,"div",7)(14,"div",8)(15,"app-dag-graph",9),h("nodeClick",function(s){return n.onNodeClick(s)}),o(),C(16,ft,2,0,"div",10),C(17,bt,1,4,"app-node-inspector",11),o(),d(18,"div",12)(19,"div",13),l(20,"\u{1F4AC} H\u1ED9i tho\u1EA1i"),o(),d(21,"div",14),P(22,vt,3,4,"div",15,mt),C(24,_t,2,0,"div",16),P(25,yt,4,5,"div",15,gt),o(),d(27,"div",17)(28,"textarea",18),be("ngModelChange",function(s){return fe(n.draft,s)||(n.draft=s),s}),o(),C(29,Ct,2,1,"div",19),d(30,"div",20)(31,"button",21),h("click",function(){return n.sendAnswer()}),l(32),o(),d(33,"button",22),h("click",function(){return n.rejectGate()}),l(34," T\u1EEB ch\u1ED1i "),o()()()()()()),e&2&&(a(7),w(n.run==null?null:n.run.workflow),a(4),w(n.run==null?null:n.run.runId),a(),E(n.run?12:-1),a(3),g("nodes",n.dagNodes)("edges",n.dagEdges)("width",n.dagWidth)("height",n.dagHeight),a(),E(!(n.run==null||n.run.graph==null||n.run.graph.nodes==null)&&n.run.graph.nodes.length?-1:16),a(),E(n.inspectorKey?17:-1),a(5),H(n.messages),a(2),E(n.messages.length&&n.feed.length?24:-1),a(),H(n.feed),a(3),he("ngModel",n.draft),g("disabled",n.gate.phase()==="submitting")("placeholder",n.gate.visible()?n.gate.submitAction()==="resume"?"Nh\u1EADp c\xE2u tr\u1EA3 l\u1EDDi\u2026":"Ph\u1EA3n h\u1ED3i (tu\u1EF3 ch\u1ECDn)\u2026":"Ch\u1EC9 tr\u1EA3 l\u1EDDi \u0111\u01B0\u1EE3c khi run \u0111ang t\u1EA1m d\u1EEBng."),a(),E(n.gate.errorMessage()?29:-1),a(2),g("disabled",!n.gate.visible()||n.gate.phase()==="submitting"||n.gate.submitAction()==="resume"&&!n.draft.trim()),a(),q(" ",n.gate.phase()==="submitting"?"\u0110ang g\u1EEDi\u2026":"G\u1EEDi"," "),a(),g("disabled",!n.gate.visible()||n.gate.phase()==="submitting"))},dependencies:[A,xe,Ne,Se,De,ke,Ie,$,J],encapsulation:2})};export{je as RunExecutionComponent};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{b as U,d as X,e as Z}from"./chunk-N3FOQ3O5.js";import{a as ee,b as te,e as ne,g as ie,h as oe,i as re,j as ae,k as le}from"./chunk-7ELOO4IC.js";import{$a as z,Ba as W,Fa as h,Ka as S,Lb as J,Mb as I,O as E,Qa as p,Qb as B,Ra as a,Sa as l,T as g,Ta as T,U as u,V as F,W as H,Xa as y,Ya as m,Za as c,_a as A,a as _,b,bb as j,cb as K,db as q,fb as O,gb as M,hb as Q,ib as d,jb as f,kb as P,lb as R,mb as x,nb as C,ob as v,qa as s,rb as G}from"./chunk-4R37VVI4.js";var ge={ratio:.5,leftCollapsed:!1,rightCollapsed:!1};function D(o,n=.15,e=.85){return Number.isNaN(o)?.5:Math.min(e,Math.max(n,o))}function se(o,n=ge){let e=b(_({},n),{rightCollapsed:n.rightCollapsed&&!n.leftCollapsed});try{let t=globalThis.localStorage?.getItem(o);if(!t)return _({},e);let i=JSON.parse(t),r=!!i.leftCollapsed;return{ratio:typeof i.ratio=="number"?D(i.ratio):e.ratio,leftCollapsed:r,rightCollapsed:!!i.rightCollapsed&&!r}}catch(t){return _({},e)}}function L(o,n){try{globalThis.localStorage?.setItem(o,JSON.stringify(n))}catch(e){}}function de(o,n){if(n==="left"){let t=!o.leftCollapsed;return b(_({},o),{leftCollapsed:t,rightCollapsed:t?!1:o.rightCollapsed})}let e=!o.rightCollapsed;return b(_({},o),{rightCollapsed:e,leftCollapsed:e?!1:o.leftCollapsed})}var _e=["host"],we=[[["","sp-left",""]],[["","sp-right",""]]],be=["[sp-left]","[sp-right]"];function xe(o,n){o&1&&(a(0,"div",8),z(1),l())}function Ce(o,n){if(o&1){let e=y();a(0,"div",9),m("mousedown",function(i){g(e);let r=c();return u(r.startDrag(i))}),l()}}function ve(o,n){o&1&&(a(0,"div",8),z(1,1),l())}var V=class o{storageKey="split-pane";leftTitle="";rightTitle="";minPx=240;host;state={ratio:.5,leftCollapsed:!1,rightCollapsed:!1};dragging=!1;moveHandler;upHandler;ngOnInit(){this.state=se(this.storageKey)}ngAfterViewInit(){queueMicrotask(()=>{let n=this.host?.nativeElement.getBoundingClientRect().width??0;if(n>0&&!this.state.leftCollapsed&&!this.state.rightCollapsed){let e=this.minPx/n,t=D(this.state.ratio,e,1-e);t!==this.state.ratio&&(this.state=b(_({},this.state),{ratio:t}))}})}leftBasis(){return this.state.leftCollapsed?"34px":this.state.rightCollapsed?"auto":this.state.ratio*100+"%"}toggle(n){this.state=de(this.state,n),L(this.storageKey,this.state)}startDrag(n){n.preventDefault(),this.dragging=!0,this.moveHandler=e=>{if(!this.dragging)return;let t=this.host.nativeElement.getBoundingClientRect();if(t.width<=0)return;let i=this.minPx/t.width;this.state=b(_({},this.state),{ratio:D((e.clientX-t.left)/t.width,i,1-i)})},this.upHandler=()=>this.endDrag(),document.addEventListener("mousemove",this.moveHandler),document.addEventListener("mouseup",this.upHandler),window.addEventListener("blur",this.upHandler)}endDrag(){this.dragging&&(this.dragging=!1,this.moveHandler&&document.removeEventListener("mousemove",this.moveHandler),this.upHandler&&(document.removeEventListener("mouseup",this.upHandler),window.removeEventListener("blur",this.upHandler)),this.moveHandler=this.upHandler=void 0,L(this.storageKey,this.state))}ngOnDestroy(){this.endDrag()}static \u0275fac=function(e){return new(e||o)};static \u0275cmp=W({type:o,selectors:[["app-split-pane"]],viewQuery:function(e,t){if(e&1&&j(_e,7),e&2){let i;K(i=q())&&(t.host=i.first)}},inputs:{storageKey:"storageKey",leftTitle:"leftTitle",rightTitle:"rightTitle",minPx:"minPx"},ngContentSelectors:be,decls:17,vars:21,consts:[["host",""],[1,"sp"],[1,"sp-pane"],[1,"sp-hd"],[1,"sp-title"],["type","button",1,"sp-min",3,"click","title"],["class","sp-bd",4,"ngIf"],["class","sp-divider",3,"mousedown",4,"ngIf"],[1,"sp-bd"],[1,"sp-divider",3,"mousedown"]],template:function(e,t){e&1&&(A(we),a(0,"div",1,0)(2,"div",2)(3,"div",3)(4,"span",4),d(5),l(),a(6,"button",5),m("click",function(){return t.toggle("left")}),d(7),l()(),h(8,xe,2,0,"div",6),l(),h(9,Ce,1,0,"div",7),a(10,"div",2)(11,"div",3)(12,"span",4),d(13),l(),a(14,"button",5),m("click",function(){return t.toggle("right")}),d(15),l()(),h(16,ve,2,0,"div",6),l()()),e&2&&(s(2),O("flex-basis",t.leftBasis())("flex-grow",t.state.leftCollapsed?0:t.state.rightCollapsed?1:0),M("collapsed",t.state.leftCollapsed),s(3),f(t.leftTitle),s(),p("title",t.state.leftCollapsed?"Restore":"Minimize"),S("aria-label",(t.state.leftCollapsed?"Restore ":"Minimize ")+t.leftTitle),s(),f(t.state.leftCollapsed?"\u25A3":"\u229F"),s(),p("ngIf",!t.state.leftCollapsed),s(),p("ngIf",!t.state.leftCollapsed&&!t.state.rightCollapsed),s(),O("flex-grow",1),M("collapsed",t.state.rightCollapsed),s(3),f(t.rightTitle),s(),p("title",t.state.rightCollapsed?"Restore":"Minimize"),S("aria-label",(t.state.rightCollapsed?"Restore ":"Minimize ")+t.rightTitle),s(),f(t.state.rightCollapsed?"\u25A3":"\u229F"),s(),p("ngIf",!t.state.rightCollapsed))},dependencies:[B,I],styles:['.sp[_ngcontent-%COMP%]{display:flex;width:100%;height:100%;min-height:470px}.sp-pane[_ngcontent-%COMP%]{display:flex;flex-direction:column;min-width:0;border:1px solid #2b2d33;border-radius:8px;background:#15161b;overflow:hidden}.sp-pane.collapsed[_ngcontent-%COMP%]{flex:0 0 34px!important}.sp-hd[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 10px;border-bottom:1px solid #2b2d33;background:#17181d;font-size:12px;color:#a1a1aa}.sp-pane.collapsed[_ngcontent-%COMP%] .sp-hd[_ngcontent-%COMP%]{writing-mode:vertical-rl;border-bottom:0;border-right:1px solid #2b2d33;height:100%;justify-content:flex-start}.sp-title[_ngcontent-%COMP%]{font-weight:700;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sp-min[_ngcontent-%COMP%]{border:0;background:transparent;color:#9ca3af;cursor:pointer;font-size:13px;line-height:1;padding:0 2px}.sp-min[_ngcontent-%COMP%]:hover{color:#e7e7ea}.sp-bd[_ngcontent-%COMP%]{flex:1;min-height:0;position:relative;overflow:auto}.sp-divider[_ngcontent-%COMP%]{flex:0 0 10px;cursor:col-resize;position:relative}.sp-divider[_ngcontent-%COMP%]:after{content:"";position:absolute;left:4px;top:0;bottom:0;width:2px;background:#2b2d33}.sp-divider[_ngcontent-%COMP%]:hover:after{background:#6366f1}@media(max-width:900px){.sp[_ngcontent-%COMP%]{flex-direction:column}.sp-divider[_ngcontent-%COMP%]{display:none}.sp-pane[_ngcontent-%COMP%]{flex:1 1 auto!important}.sp-pane.collapsed[_ngcontent-%COMP%]{flex:0 0 34px!important}.sp-pane.collapsed[_ngcontent-%COMP%] .sp-hd[_ngcontent-%COMP%]{writing-mode:horizontal-tb;border-right:0;border-bottom:1px solid #2b2d33;height:auto}}']})};var ye=o=>["/runs",o];function Me(o,n){if(o&1){let e=y();a(0,"button",37),m("dragstart",function(i){let r=g(e).$implicit,w=c();return u(w.onPaletteDragStart(i,r.type))})("click",function(){let i=g(e).$implicit,r=c();return u(r.addNode(i.type))}),a(1,"span",38),d(2),l(),a(3,"span")(4,"strong"),d(5),l(),a(6,"small"),d(7),l()()()}if(o&2){let e=n.$implicit,t=c();s(2),f(t.iconFor(e.type)),s(3),f(e.label),s(2),f(e.description)}}function ke(o,n){if(o&1){let e=y();a(0,"button",39),m("click",function(){let i=g(e).$implicit,r=c();return u(r.loadWorkflow(i.id))}),a(1,"span"),d(2),l(),a(3,"small"),d(4),l()()}if(o&2){let e=n.$implicit;s(2),f(e.name),s(2),P("",e.nodeCount," nodes")}}function Se(o,n){if(o&1&&(a(0,"a",40)(1,"span")(2,"strong"),d(3),l(),a(4,"small"),d(5),l()(),a(6,"em"),d(7),l()()),o&2){let e=n.$implicit,t=c();p("routerLink",G(6,ye,e.runId)),s(3),f(e.workflow),s(2),f(e.runId),s(),Q(t.statusClass(e.status)),s(),f(e.status)}}function Oe(o,n){o&1&&(a(0,"p",41),d(1,"No runs yet."),l())}function Pe(o,n){if(o&1&&(a(0,"div",42),d(1),l()),o&2){let e=c();M("error",e.saveState==="error"),s(),P(" ",e.statusMessage," ")}}function Ne(o,n){o&1&&(a(0,"div",43)(1,"h2"),d(2,"Drop nodes here"),l(),a(3,"p"),d(4,"Build a DAG by adding Bash, Command, and Prompt nodes."),l()())}function Ee(o,n){if(o&1&&(F(),T(0,"line")),o&2){let e=n.$implicit;S("x1",e.x1)("y1",e.y1)("x2",e.x2)("y2",e.y2)}}function We(o,n){if(o&1){let e=y();a(0,"button",44),m("click",function(){let i=g(e).$implicit,r=c();return u(r.selectNode(i))})("dragstart",function(i){let r=g(e).$implicit,w=c();return u(w.onNodeDragStart(i,r))}),a(1,"span",45),d(2),l(),a(3,"span",46)(4,"strong"),d(5),l(),a(6,"small"),d(7),l()()()}if(o&2){let e=n.$implicit,t=c();O("left",e.x,"px")("top",e.y,"px"),M("selected",(t.selectedNode==null?null:t.selectedNode.id)===e.id),s(2),f(t.iconFor(e.type)),s(3),f(e.id),s(2),R("",e.type," \xB7 ",e.dependsOn.length||0," deps")}}function Te(o,n){if(o&1&&(a(0,"option",71),d(1),l()),o&2){let e=n.$implicit;p("value",e.name)("disabled",!e.available),s(),R(" ",e.name,"",e.available?"":" \u2014 not available on this machine"," ")}}function Ie(o,n){if(o&1&&T(0,"option",72),o&2){let e=n.$implicit;p("value",e)}}function Be(o,n){if(o&1){let e=y();a(0,"label",73)(1,"input",74),m("change",function(i){let r=g(e).$implicit,w=c(2);return u(w.toggleDependency(r.id,i))}),l(),a(2,"span"),d(3),l()()}if(o&2){let e=n.$implicit,t=c(2);s(),p("checked",t.selectedNode.dependsOn.includes(e.id)),s(2),f(e.id)}}function De(o,n){if(o&1){let e=y();a(0,"aside",47)(1,"div",48)(2,"span",49),d(3,"Inspector"),l(),a(4,"button",50),m("click",function(){g(e);let i=c();return u(i.closeInspector())}),d(5,"\u2715"),l()(),a(6,"label",51),d(7,"Node ID"),l(),a(8,"input",52),m("ngModelChange",function(i){g(e);let r=c();return u(r.renameSelectedNode(i))}),l(),a(9,"label",53),d(10,"Type"),l(),a(11,"select",54),v("ngModelChange",function(i){g(e);let r=c();return C(r.selectedNode.type,i)||(r.selectedNode.type=i),u(i)}),m("ngModelChange",function(){g(e);let i=c();return u(i.refreshYaml())}),a(12,"option",55),d(13,"bash"),l(),a(14,"option",56),d(15,"command"),l(),a(16,"option",57),d(17,"prompt"),l()(),a(18,"label",58),d(19,"Content"),l(),a(20,"textarea",59),v("ngModelChange",function(i){g(e);let r=c();return C(r.selectedNode.content,i)||(r.selectedNode.content=i),u(i)}),m("ngModelChange",function(){g(e);let i=c();return u(i.refreshYaml())}),l(),a(21,"label",60),d(22,"Provider"),l(),a(23,"select",61),v("ngModelChange",function(i){g(e);let r=c();return C(r.selectedNode.provider,i)||(r.selectedNode.provider=i),u(i)}),m("ngModelChange",function(){g(e);let i=c();return u(i.refreshYaml())}),a(24,"option",62),d(25,"(inherit workflow)"),l(),h(26,Te,2,4,"option",63),l(),a(27,"label",64),d(28,"Model"),l(),a(29,"input",65),v("ngModelChange",function(i){g(e);let r=c();return C(r.selectedNode.model,i)||(r.selectedNode.model=i),u(i)}),m("ngModelChange",function(){g(e);let i=c();return u(i.refreshYaml())}),l(),a(30,"datalist",66),h(31,Ie,1,1,"option",67),l(),a(32,"label",68),d(33,"Depends on"),l(),h(34,Be,4,2,"label",69),a(35,"button",70),m("click",function(){g(e);let i=c();return u(i.deleteSelectedNode())}),d(36,"Delete Node"),l()()}if(o&2){let e=c();s(8),p("ngModel",e.selectedNode.id),s(3),x("ngModel",e.selectedNode.type),s(9),x("ngModel",e.selectedNode.content),s(3),x("ngModel",e.selectedNode.provider),s(3),p("ngForOf",e.providers),s(3),x("ngModel",e.selectedNode.model),s(2),p("ngForOf",e.modelSuggestions),s(3),p("ngForOf",e.dependencyCandidates)}}var pe=class o{api=E(le);router=E(X);route=E(U);palette=[{type:"bash",label:"Bash",description:"Run a shell step"},{type:"command",label:"Command",description:"Use a .vsaf command"},{type:"prompt",label:"Prompt",description:"Call an AI provider"}];workflowName="new-workflow";workflowFolder="";description="Draft workflow";nodes=[];selectedNode;workflows=[];runs=[];providers=[];yamlPreview="";saveState="idle";statusMessage="";draggingType;draggingNodeId;ngOnInit(){this.workflowFolder=$(this.route.snapshot.queryParamMap.get("folder")??""),this.refreshData(),this.resetBuilder();let n=this.route.snapshot.queryParamMap.get("edit");n&&this.loadWorkflow(n)}refreshData(){this.api.getWorkflows().subscribe(n=>this.workflows=n),this.api.getRuns().subscribe(n=>this.runs=n.slice().reverse().slice(0,8)),this.api.getProviders().subscribe({next:n=>this.providers=n.providers??[],error:()=>this.providers=[]})}get modelSuggestions(){let n=this.selectedNode?.provider||ce;return this.providers.find(e=>e.name===n)?.defaultModels??[]}resetBuilder(){this.workflowName="new-workflow",this.description="Draft workflow",this.nodes=[this.makeNode("bash",80,100,"setup"),this.makeNode("command",330,170,"review")],this.nodes[1].dependsOn=[this.nodes[0].id],this.selectedNode=this.nodes[0],this.setStatus(""),this.refreshYaml()}get workflowId(){let n=$(this.workflowFolder),e=k(this.workflowName);return n?`${n}/${e}`:e}onPaletteDragStart(n,e){this.draggingType=e,n.dataTransfer?.setData("application/x-vsaf-node-type",e),n.dataTransfer?.setData("text/plain",e)}onNodeDragStart(n,e){this.draggingNodeId=e.id,n.dataTransfer?.setData("application/x-vsaf-node-id",e.id)}onCanvasDragOver(n){n.preventDefault()}onCanvasDrop(n){n.preventDefault();let e=n.currentTarget.getBoundingClientRect(),t=Math.max(18,n.clientX-e.left-95),i=Math.max(18,n.clientY-e.top-24),r=n.dataTransfer?.getData("application/x-vsaf-node-id")||this.draggingNodeId;if(r){let N=this.nodes.find(me=>me.id===r);N&&(N.x=t,N.y=i,this.selectNode(N),this.refreshYaml()),this.draggingNodeId=void 0;return}let w=n.dataTransfer?.getData("application/x-vsaf-node-type")||this.draggingType;w&&this.addNode(w,t,i),this.draggingType=void 0}addNode(n,e=90+this.nodes.length*34,t=90+this.nodes.length*42){let i=this.makeNode(n,e,t);this.nodes=[...this.nodes,i],this.selectNode(i),this.refreshYaml()}selectNode(n){this.selectedNode=n}closeInspector(){this.selectedNode=void 0}renameSelectedNode(n){if(!this.selectedNode)return;let e=k(n);if(!e)return;let t=this.selectedNode.id;if(t!==e){if(this.nodes.some(i=>i.id===e)){this.setStatus(`Node ID already exists: ${e}`,"error");return}this.selectedNode.id=e;for(let i of this.nodes)i.dependsOn=i.dependsOn.map(r=>r===t?e:r);this.refreshYaml()}}toggleDependency(n,e){if(!this.selectedNode)return;e.target.checked?this.selectedNode.dependsOn=[...new Set([...this.selectedNode.dependsOn,n])]:this.selectedNode.dependsOn=this.selectedNode.dependsOn.filter(i=>i!==n),this.refreshYaml()}deleteSelectedNode(){if(!this.selectedNode)return;let n=this.selectedNode.id;this.nodes=this.nodes.filter(e=>e.id!==n).map(e=>b(_({},e),{dependsOn:e.dependsOn.filter(t=>t!==n)})),this.selectedNode=this.nodes[0],this.refreshYaml()}loadWorkflow(n){this.api.getWorkflow(n).subscribe(e=>{let t=e.id.lastIndexOf("/");this.workflowFolder=t>=0?e.id.slice(0,t):"",this.workflowName=t>=0?e.id.slice(t+1):e.id,this.description=e.description||"Workflow loaded from disk",this.nodes=e.nodes.map((i,r)=>({id:i.id,type:i.type,title:i.id,content:i.content,dependsOn:i.dependsOn,provider:i.provider??"",model:i.model??"",x:80+r%3*250,y:80+Math.floor(r/3)*120})),this.selectedNode=this.nodes[0],this.setStatus(`Loaded ${e.name}`),this.refreshYaml()})}saveWorkflow(){this.saveCurrentWorkflow()}runWorkflow(){this.saveCurrentWorkflow(n=>{this.api.startRun(n,"").subscribe({next:e=>this.router.navigate(["/runs",e.runId]),error:e=>this.setStatus(e?.error?.error??e?.message??"Run failed","error")})})}refreshYaml(){this.yamlPreview=Fe(this.workflowName,this.description,this.nodes),this.saveState==="saved"&&(this.saveState="idle")}get dependencyCandidates(){return this.selectedNode?this.nodes.filter(n=>n.id!==this.selectedNode.id):[]}get edges(){let n=new Map(this.nodes.map(t=>[t.id,t])),e=[];for(let t of this.nodes)for(let i of t.dependsOn){let r=n.get(i);r&&e.push({x1:r.x+190,y1:r.y+28,x2:t.x,y2:t.y+28})}return e}iconFor(n){switch(n){case"bash":return"$";case"command":return"/";case"prompt":return"AI"}}statusClass(n){switch(n){case"completed":return"status-completed";case"failed":return"status-failed";case"running":return"status-running";default:return"status-default"}}saveCurrentWorkflow(n){let e=k(this.workflowName),t=$(this.workflowFolder),i=t?`${t}/${e}`:e;if(!e||this.nodes.length===0){this.setStatus("Workflow name and at least one node are required.","error");return}this.workflowName=e,this.refreshYaml(),this.saveState="saving",this.api.saveWorkflow(i,this.yamlPreview).subscribe({next:()=>{this.saveState="saved",this.setStatus(`Saved ${i}`),this.refreshData(),n?.(i)},error:r=>{this.saveState="error",this.setStatus(r?.error?.error??r?.message??"Save failed","error")}})}makeNode(n,e,t,i=n){let r=ze(this.nodes.map(w=>w.id),`${n}-${i}`);return{id:r,type:n,title:r,content:Ve(n,r),dependsOn:[],provider:"",model:"",x:e,y:t}}setStatus(n,e="idle"){this.statusMessage=n,this.saveState=e}static \u0275fac=function(e){return new(e||o)};static \u0275cmp=W({type:o,selectors:[["app-workflow-builder"]],decls:59,vars:18,consts:[[1,"builder-shell"],[1,"sidebar"],[1,"brand-row"],[1,"brand-mark"],[1,"brand-title"],[1,"brand-subtitle"],["for","workflow-folder",1,"field-label"],["id","workflow-folder","placeholder","e.g. sdlc/release",1,"text-input",3,"ngModelChange","ngModel"],["for","workflow-name",1,"field-label"],["id","workflow-name",1,"text-input",3,"ngModelChange","ngModel"],["for","workflow-description",1,"field-label"],["id","workflow-description","rows","3",1,"text-area",3,"ngModelChange","ngModel"],[1,"section-title"],["type","button","class","palette-item","draggable","true",3,"dragstart","click",4,"ngFor","ngForOf"],["type","button","class","workflow-link",3,"click",4,"ngFor","ngForOf"],["open","",1,"runs-details"],["class","run-row",3,"routerLink",4,"ngFor","ngForOf"],["class","muted",4,"ngIf"],[1,"workspace"],[1,"toolbar"],[1,"toolbar-actions"],["type","button",1,"ghost-button",3,"click"],["type","button",1,"primary-button",3,"click","disabled"],["type","button",1,"run-button",3,"click","disabled"],["class","status-row",3,"error",4,"ngIf"],[1,"workspace-split"],["storageKey","wf-builder-split","leftTitle","Canvas","rightTitle","Workflow YAML"],["sp-left","",1,"canvas-wrap"],[1,"canvas",3,"dragover","drop"],[1,"canvas-grid"],["class","empty-state",4,"ngIf"],["aria-hidden","true",1,"edges"],[4,"ngFor","ngForOf"],["type","button","class","node-card","draggable","true",3,"selected","left","top","click","dragstart",4,"ngFor","ngForOf"],["class","inspector-drawer",4,"ngIf"],["sp-right","",1,"yaml-wrap"],[1,"yaml-editor",3,"ngModelChange","ngModel"],["type","button","draggable","true",1,"palette-item",3,"dragstart","click"],[1,"palette-icon"],["type","button",1,"workflow-link",3,"click"],[1,"run-row",3,"routerLink"],[1,"muted"],[1,"status-row"],[1,"empty-state"],["type","button","draggable","true",1,"node-card",3,"click","dragstart"],[1,"node-kind"],[1,"node-copy"],[1,"inspector-drawer"],[1,"drawer-hd"],[1,"panel-title"],["type","button","title","Close",1,"icon-button",3,"click"],["for","node-id",1,"field-label"],["id","node-id",1,"text-input",3,"ngModelChange","ngModel"],["for","node-type",1,"field-label"],["id","node-type",1,"text-input",3,"ngModelChange","ngModel"],["value","bash"],["value","command"],["value","prompt"],["for","node-content",1,"field-label"],["id","node-content","rows","7",1,"text-area","mono",3,"ngModelChange","ngModel"],["for","node-provider",1,"field-label"],["id","node-provider",1,"text-input",3,"ngModelChange","ngModel"],["value",""],[3,"value","disabled",4,"ngFor","ngForOf"],["for","node-model",1,"field-label"],["id","node-model","list","builder-model-suggestions","placeholder","(inherit)",1,"text-input",3,"ngModelChange","ngModel"],["id","builder-model-suggestions"],[3,"value",4,"ngFor","ngForOf"],[1,"field-label"],["class","check-row",4,"ngFor","ngForOf"],["type","button",1,"danger-button",3,"click"],[3,"value","disabled"],[3,"value"],[1,"check-row"],["type","checkbox",3,"change","checked"]],template:function(e,t){e&1&&(a(0,"section",0)(1,"aside",1)(2,"div",2)(3,"div",3),d(4,"V"),l(),a(5,"div")(6,"div",4),d(7,"VSAF Builder"),l(),a(8,"div",5),d(9,"Workflow canvas"),l()()(),a(10,"label",6),d(11,"Folder"),l(),a(12,"input",7),v("ngModelChange",function(r){return C(t.workflowFolder,r)||(t.workflowFolder=r),r}),l(),a(13,"label",8),d(14,"Workflow name"),l(),a(15,"input",9),v("ngModelChange",function(r){return C(t.workflowName,r)||(t.workflowName=r),r}),m("ngModelChange",function(){return t.refreshYaml()}),l(),a(16,"label",10),d(17,"Description"),l(),a(18,"textarea",11),v("ngModelChange",function(r){return C(t.description,r)||(t.description=r),r}),m("ngModelChange",function(){return t.refreshYaml()}),l(),a(19,"div",12),d(20,"Node Palette"),l(),h(21,Me,8,3,"button",13),a(22,"div",12),d(23,"Existing"),l(),h(24,ke,5,2,"button",14),a(25,"details",15)(26,"summary",12),d(27,"Recent Runs"),l(),h(28,Se,8,8,"a",16)(29,Oe,2,0,"p",17),l()(),a(30,"main",18)(31,"header",19)(32,"div")(33,"h1"),d(34),l(),a(35,"p"),d(36),l()(),a(37,"div",20)(38,"button",21),m("click",function(){return t.resetBuilder()}),d(39,"New"),l(),a(40,"button",21),m("click",function(){return t.refreshData()}),d(41,"Reload"),l(),a(42,"button",22),m("click",function(){return t.saveWorkflow()}),d(43),l(),a(44,"button",23),m("click",function(){return t.runWorkflow()}),d(45,"Run"),l()()(),h(46,Pe,2,3,"div",24),a(47,"div",25)(48,"app-split-pane",26)(49,"div",27)(50,"section",28),m("dragover",function(r){return t.onCanvasDragOver(r)})("drop",function(r){return t.onCanvasDrop(r)}),T(51,"div",29),h(52,Ne,5,0,"div",30),F(),a(53,"svg",31),h(54,Ee,1,4,"line",32),l(),h(55,We,8,10,"button",33),l(),h(56,De,37,8,"aside",34),l(),H(),a(57,"div",35)(58,"textarea",36),v("ngModelChange",function(r){return C(t.yamlPreview,r)||(t.yamlPreview=r),r}),l()()()()()()),e&2&&(s(12),x("ngModel",t.workflowFolder),s(3),x("ngModel",t.workflowName),s(3),x("ngModel",t.description),s(3),p("ngForOf",t.palette),s(3),p("ngForOf",t.workflows),s(4),p("ngForOf",t.runs),s(),p("ngIf",t.runs.length===0),s(5),f(t.workflowId||"untitled-workflow"),s(2),P("",t.nodes.length," nodes \xB7 drag from palette or click a node to edit"),s(6),p("disabled",t.saveState==="saving"),s(),P(" ",t.saveState==="saving"?"Saving...":"Save Workflow"," "),s(),p("disabled",t.nodes.length===0),s(2),p("ngIf",t.statusMessage),s(6),p("ngIf",t.nodes.length===0),s(2),p("ngForOf",t.edges),s(),p("ngForOf",t.nodes),s(),p("ngIf",t.selectedNode),s(2),x("ngModel",t.yamlPreview))},dependencies:[B,J,I,ae,oe,re,ee,ie,te,ne,Z,V],styles:["[_nghost-%COMP%]{display:block;min-height:calc(100vh - 56px);background:#101114;color:#e7e7ea}button[_ngcontent-%COMP%], input[_ngcontent-%COMP%], textarea[_ngcontent-%COMP%], select[_ngcontent-%COMP%]{font:inherit}.builder-shell[_ngcontent-%COMP%]{display:grid;grid-template-columns:280px minmax(0,1fr);min-height:calc(100vh - 56px)}.sidebar[_ngcontent-%COMP%]{border-right:1px solid #2b2d33;background:#17181d;padding:16px;overflow:auto}.brand-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;margin-bottom:22px}.brand-mark[_ngcontent-%COMP%]{display:grid;place-items:center;width:34px;height:34px;border-radius:8px;background:#6366f1;color:#fff;font-weight:700}.brand-title[_ngcontent-%COMP%]{font-size:15px;font-weight:700}.brand-subtitle[_ngcontent-%COMP%], .muted[_ngcontent-%COMP%], small[_ngcontent-%COMP%]{color:#9ca3af}.field-label[_ngcontent-%COMP%], .section-title[_ngcontent-%COMP%]{display:block;margin:14px 0 7px;color:#a1a1aa;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em}.text-input[_ngcontent-%COMP%], .text-area[_ngcontent-%COMP%]{width:100%;box-sizing:border-box;border:1px solid #333640;border-radius:7px;background:#101114;color:#f4f4f5;padding:9px 10px;outline:none}.text-input[_ngcontent-%COMP%]:focus, .text-area[_ngcontent-%COMP%]:focus, .yaml-editor[_ngcontent-%COMP%]:focus{border-color:#6366f1;box-shadow:0 0 0 2px #6366f12e}.text-area[_ngcontent-%COMP%]{resize:vertical}.mono[_ngcontent-%COMP%], .yaml-editor[_ngcontent-%COMP%]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.palette-item[_ngcontent-%COMP%], .workflow-link[_ngcontent-%COMP%]{display:flex;align-items:center;gap:10px;width:100%;border:1px solid #2b2d33;border-radius:8px;background:#1f2128;color:#e7e7ea;padding:10px;margin-bottom:8px;text-align:left;cursor:grab}.palette-item[_ngcontent-%COMP%]:hover, .workflow-link[_ngcontent-%COMP%]:hover{border-color:#4f46e5;background:#242633}.palette-icon[_ngcontent-%COMP%]{display:grid;place-items:center;width:28px;height:28px;border-radius:7px;background:#111827;color:#a5b4fc}.palette-item[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .workflow-link[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{display:block;font-size:13px}.palette-item[_ngcontent-%COMP%] small[_ngcontent-%COMP%], .workflow-link[_ngcontent-%COMP%] small[_ngcontent-%COMP%]{display:block;font-size:11px;margin-top:2px}.workflow-link[_ngcontent-%COMP%]{justify-content:space-between;cursor:pointer}.runs-details[_ngcontent-%COMP%]{margin-top:8px}.runs-details[_ngcontent-%COMP%] > summary[_ngcontent-%COMP%]{cursor:pointer;list-style:revert}.workspace[_ngcontent-%COMP%]{min-width:0;padding:18px;display:flex;flex-direction:column;min-height:0}.toolbar[_ngcontent-%COMP%]{display:flex;justify-content:space-between;gap:16px;align-items:center;margin-bottom:12px}.toolbar[_ngcontent-%COMP%] h1[_ngcontent-%COMP%]{margin:0;font-size:20px}.toolbar[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:4px 0 0;color:#9ca3af;font-size:13px}.toolbar-actions[_ngcontent-%COMP%]{display:flex;gap:8px;flex-wrap:wrap}.ghost-button[_ngcontent-%COMP%], .primary-button[_ngcontent-%COMP%], .run-button[_ngcontent-%COMP%], .danger-button[_ngcontent-%COMP%]{border:1px solid #333640;border-radius:7px;padding:8px 12px;color:#f4f4f5;background:#20222a;cursor:pointer}.primary-button[_ngcontent-%COMP%]{background:#4f46e5;border-color:#4f46e5}.run-button[_ngcontent-%COMP%]{background:#059669;border-color:#059669}.danger-button[_ngcontent-%COMP%]{width:100%;margin-top:14px;background:#3f1d24;border-color:#7f1d1d;color:#fecaca}.primary-button[_ngcontent-%COMP%]:disabled, .run-button[_ngcontent-%COMP%]:disabled{opacity:.55;cursor:not-allowed}.status-row[_ngcontent-%COMP%]{border:1px solid #1f5f45;border-radius:8px;background:#092d22;color:#a7f3d0;padding:10px 12px;margin-bottom:12px;font-size:13px}.status-row.error[_ngcontent-%COMP%]{border-color:#7f1d1d;background:#2a1217;color:#fecaca}.workspace-split[_ngcontent-%COMP%]{flex:1;min-height:470px}.canvas-wrap[_ngcontent-%COMP%]{position:relative;height:100%;min-height:470px}.canvas[_ngcontent-%COMP%]{position:absolute;inset:0;overflow:hidden;border:0;border-radius:0;background:#15161b}.inspector-drawer[_ngcontent-%COMP%]{position:absolute;top:0;right:0;bottom:0;width:min(360px,72%);background:#17181d;border-left:1px solid #2b2d33;box-shadow:-14px 0 30px #0006;padding:14px;overflow:auto;z-index:5}.drawer-hd[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.icon-button[_ngcontent-%COMP%]{border:0;background:transparent;color:#9ca3af;cursor:pointer;font-size:15px;line-height:1}.icon-button[_ngcontent-%COMP%]:hover{color:#e7e7ea}.canvas-grid[_ngcontent-%COMP%]{position:absolute;inset:0;background-image:linear-gradient(#24262e 1px,transparent 1px),linear-gradient(90deg,#24262e 1px,transparent 1px);background-size:28px 28px;opacity:.45}.empty-state[_ngcontent-%COMP%]{position:absolute;inset:0;display:grid;place-content:center;text-align:center;color:#9ca3af;pointer-events:none}.empty-state[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin:0 0 6px;color:#e7e7ea}.edges[_ngcontent-%COMP%]{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}.edges[_ngcontent-%COMP%] line[_ngcontent-%COMP%]{stroke:#6366f1;stroke-width:2;stroke-dasharray:5 5;opacity:.8}.node-card[_ngcontent-%COMP%]{position:absolute;z-index:2;display:flex;align-items:center;gap:10px;width:190px;border:1px solid #3f4250;border-radius:8px;background:#20222a;color:#f4f4f5;padding:11px;cursor:move;text-align:left;box-shadow:0 12px 28px #00000038}.node-card.selected[_ngcontent-%COMP%]{border-color:#818cf8;box-shadow:0 0 0 2px #6366f147,0 12px 28px #00000038}.node-kind[_ngcontent-%COMP%]{display:grid;place-items:center;width:30px;height:30px;border-radius:7px;background:#111827;color:#a5b4fc}.node-copy[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .node-copy[_ngcontent-%COMP%] small[_ngcontent-%COMP%]{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-copy[_ngcontent-%COMP%]{min-width:0}.panel-title[_ngcontent-%COMP%]{margin-bottom:12px;font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:#d4d4d8}.check-row[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;margin:8px 0;color:#d4d4d8;font-size:13px}.yaml-editor[_ngcontent-%COMP%]{width:100%;min-height:260px;box-sizing:border-box;border:1px solid #333640;border-radius:7px;background:#0f1014;color:#d4d4d8;padding:12px;resize:vertical}.yaml-wrap[_ngcontent-%COMP%]{height:100%}.yaml-wrap[_ngcontent-%COMP%] .yaml-editor[_ngcontent-%COMP%]{width:100%;height:100%;min-height:0;box-sizing:border-box;border:0;border-radius:0;resize:none}.run-row[_ngcontent-%COMP%]{display:flex;justify-content:space-between;gap:12px;padding:10px 0;color:#e7e7ea;text-decoration:none;border-bottom:1px solid #252730}.run-row[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .run-row[_ngcontent-%COMP%] small[_ngcontent-%COMP%]{display:block}.run-row[_ngcontent-%COMP%] small[_ngcontent-%COMP%]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.status-completed[_ngcontent-%COMP%]{color:#34d399}.status-failed[_ngcontent-%COMP%]{color:#f87171}.status-running[_ngcontent-%COMP%]{color:#60a5fa}.status-default[_ngcontent-%COMP%]{color:#a1a1aa}@media(max-width:980px){.builder-shell[_ngcontent-%COMP%]{grid-template-columns:1fr}.sidebar[_ngcontent-%COMP%]{border-right:0;border-bottom:1px solid #2b2d33}.toolbar[_ngcontent-%COMP%]{align-items:flex-start;flex-direction:column}}"]})};function Ve(o,n){switch(o){case"bash":return`echo "${n}"`;case"command":return n;case"prompt":return`Complete ${n} and summarize the result.`}}var ce="claude";function Fe(o,n,e){let t=[`name: ${k(o)||"new-workflow"}`,`description: ${Y(n||"Draft workflow")}`,`provider: ${ce}`,"model: sonnet","nodes:"];for(let i of e)if(t.push(` - id: ${i.id}`),i.dependsOn.length>0&&t.push(` depends_on: [${i.dependsOn.join(", ")}]`),i.provider&&t.push(` provider: ${i.provider}`),i.model&&t.push(` model: ${i.model}`),i.type==="bash")t.push(` bash: ${Y(i.content||"echo ok")}`);else if(i.type==="command")t.push(` command: ${Y(i.content||i.id)}`);else{t.push(" prompt: |");for(let r of(i.content||`Complete ${i.id}`).split(`
|
|
2
|
-
`))t.push(` ${r}`)}return`${t.join(`
|
|
3
|
-
`)}
|
|
4
|
-
`}function k(o){return o.trim().toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}function $(o){return o.split("/").map(k).filter(Boolean).join("/")}function ze(o,n){let e=k(n)||"node";if(!o.includes(e))return e;let t=2;for(;o.includes(`${e}-${t}`);)t++;return`${e}-${t}`}function Y(o){return JSON.stringify(o)}export{pe as WorkflowBuilderComponent};
|