mirror of
https://github.com/lordmathis/llamactl.git
synced 2025-11-06 00:54:23 +00:00
Implement instance creation and editing modal
This commit is contained in:
546
ui/package-lock.json
generated
546
ui/package-lock.json
generated
@@ -9,6 +9,9 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-checkbox": "^1.3.2",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-label": "^2.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
@@ -17,7 +20,8 @@
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss": "^4.1.11"
|
||||
"tailwindcss": "^4.1.11",
|
||||
"zod": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.15",
|
||||
@@ -787,6 +791,42 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/primitive": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
|
||||
"integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-checkbox": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz",
|
||||
"integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-presence": "1.1.4",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2",
|
||||
"@radix-ui/react-use-previous": "1.1.1",
|
||||
"@radix-ui/react-use-size": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
|
||||
@@ -802,6 +842,236 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-context": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
|
||||
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-dialog": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz",
|
||||
"integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.10",
|
||||
"@radix-ui/react-focus-guards": "1.1.2",
|
||||
"@radix-ui/react-focus-scope": "1.1.7",
|
||||
"@radix-ui/react-id": "1.1.1",
|
||||
"@radix-ui/react-portal": "1.1.9",
|
||||
"@radix-ui/react-presence": "1.1.4",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-slot": "1.2.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2",
|
||||
"aria-hidden": "^1.2.4",
|
||||
"react-remove-scroll": "^2.6.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-dismissable-layer": {
|
||||
"version": "1.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz",
|
||||
"integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.2",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||
"@radix-ui/react-use-escape-keydown": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-focus-guards": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz",
|
||||
"integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-focus-scope": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
|
||||
"integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-id": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
|
||||
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-label": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz",
|
||||
"integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-portal": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
|
||||
"integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-presence": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz",
|
||||
"integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
||||
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
|
||||
@@ -820,6 +1090,124 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
||||
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-controllable-state": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
|
||||
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-effect-event": "0.0.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-effect-event": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
|
||||
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-escape-keydown": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
|
||||
"integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
|
||||
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-previous": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
|
||||
"integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-size": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
|
||||
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0-beta.27",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
|
||||
@@ -1424,7 +1812,7 @@
|
||||
"version": "19.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
|
||||
"integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.0.0"
|
||||
@@ -1451,6 +1839,18 @@
|
||||
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aria-hidden": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
|
||||
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.25.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
|
||||
@@ -1576,6 +1976,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node-es": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
|
||||
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.187",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz",
|
||||
@@ -1685,6 +2091,15 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-nonce": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
|
||||
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
@@ -2134,6 +2549,75 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-remove-scroll": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
|
||||
"integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-remove-scroll-bar": "^2.3.7",
|
||||
"react-style-singleton": "^2.2.3",
|
||||
"tslib": "^2.1.0",
|
||||
"use-callback-ref": "^1.3.3",
|
||||
"use-sidecar": "^1.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-remove-scroll-bar": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
|
||||
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-style-singleton": "^2.2.2",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-style-singleton": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
|
||||
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-nonce": "^1.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.45.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz",
|
||||
@@ -2265,6 +2749,12 @@
|
||||
"url": "https://github.com/sponsors/SuperchupuDev"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tw-animate-css": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.5.tgz",
|
||||
@@ -2327,6 +2817,49 @@
|
||||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-callback-ref": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
|
||||
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/use-sidecar": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
|
||||
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-node-es": "^1.1.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.5.tgz",
|
||||
@@ -2407,6 +2940,15 @@
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.0.5.tgz",
|
||||
"integrity": "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-checkbox": "^1.3.2",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-label": "^2.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
@@ -20,7 +23,8 @@
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss": "^4.1.11"
|
||||
"tailwindcss": "^4.1.11",
|
||||
"zod": "^4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.0.15",
|
||||
|
||||
@@ -1,25 +1,43 @@
|
||||
import { useState } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import InstanceModal from '@/components/InstanceModal'
|
||||
import { CreateInstanceOptions } from '@/types/instance'
|
||||
|
||||
function Header() {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
|
||||
const handleCreateInstance = () => {
|
||||
// TODO: Open create instance dialog
|
||||
console.log('Create instance clicked')
|
||||
setIsModalOpen(true)
|
||||
}
|
||||
|
||||
const handleSaveInstance = (name: string, options: CreateInstanceOptions) => {
|
||||
// TODO: Implement API call to create instance
|
||||
console.log('Creating instance:', { name, options })
|
||||
// For now, just log the data - you'll implement the API call later
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="bg-white border-b border-gray-200">
|
||||
<div className="container mx-auto max-w-4xl px-4 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-2xl font-bold text-gray-900">
|
||||
LlamaCtl Dashboard
|
||||
</h1>
|
||||
|
||||
<Button onClick={handleCreateInstance}>
|
||||
Create Instance
|
||||
</Button>
|
||||
<>
|
||||
<header className="bg-white border-b border-gray-200">
|
||||
<div className="container mx-auto max-w-4xl px-4 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-2xl font-bold text-gray-900">
|
||||
LlamaCtl Dashboard
|
||||
</h1>
|
||||
|
||||
<Button onClick={handleCreateInstance}>
|
||||
Create Instance
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
<InstanceModal
|
||||
open={isModalOpen}
|
||||
onOpenChange={setIsModalOpen}
|
||||
onSave={handleSaveInstance}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
212
ui/src/components/InstanceModal.tsx
Normal file
212
ui/src/components/InstanceModal.tsx
Normal file
@@ -0,0 +1,212 @@
|
||||
// ui/src/components/InstanceModal.tsx
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { CreateInstanceOptions, Instance } from '@/types/instance'
|
||||
import { getBasicFields, getAdvancedFields } from '@/lib/zodFormUtils'
|
||||
import { ChevronDown, ChevronRight } from 'lucide-react'
|
||||
import ZodFormField from '@/components/ZodFormField'
|
||||
|
||||
interface InstanceModalProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
onSave: (name: string, options: CreateInstanceOptions) => void
|
||||
instance?: Instance // For editing existing instance
|
||||
}
|
||||
|
||||
const InstanceModal: React.FC<InstanceModalProps> = ({
|
||||
open,
|
||||
onOpenChange,
|
||||
onSave,
|
||||
instance
|
||||
}) => {
|
||||
const isEditing = !!instance
|
||||
|
||||
const [instanceName, setInstanceName] = useState('')
|
||||
const [formData, setFormData] = useState<CreateInstanceOptions>({})
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
const [nameError, setNameError] = useState('')
|
||||
|
||||
// Get field lists dynamically from the type
|
||||
const basicFields = getBasicFields()
|
||||
const advancedFields = getAdvancedFields()
|
||||
|
||||
// Reset form when modal opens/closes or when instance changes
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
if (instance) {
|
||||
// Populate form with existing instance data
|
||||
setInstanceName(instance.name)
|
||||
setFormData(instance.options || {})
|
||||
} else {
|
||||
// Reset form for new instance
|
||||
setInstanceName('')
|
||||
setFormData({
|
||||
auto_restart: true, // Default value
|
||||
})
|
||||
}
|
||||
setShowAdvanced(false) // Always start with basic view
|
||||
setNameError('') // Reset any name errors
|
||||
}
|
||||
}, [open, instance])
|
||||
|
||||
const handleFieldChange = (key: keyof CreateInstanceOptions, value: any) => {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[key]: value
|
||||
}))
|
||||
}
|
||||
|
||||
const handleNameChange = (name: string) => {
|
||||
setInstanceName(name)
|
||||
// Validate instance name
|
||||
if (!name.trim()) {
|
||||
setNameError('Instance name is required')
|
||||
} else if (!/^[a-zA-Z0-9-_]+$/.test(name)) {
|
||||
setNameError('Instance name can only contain letters, numbers, hyphens, and underscores')
|
||||
} else {
|
||||
setNameError('')
|
||||
}
|
||||
}
|
||||
|
||||
const handleSave = () => {
|
||||
// Validate instance name before saving
|
||||
if (!instanceName.trim()) {
|
||||
setNameError('Instance name is required')
|
||||
return
|
||||
}
|
||||
|
||||
// Clean up undefined values to avoid sending empty fields
|
||||
const cleanOptions: CreateInstanceOptions = {}
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== '' && value !== null) {
|
||||
// Handle arrays - don't include empty arrays
|
||||
if (Array.isArray(value) && value.length === 0) {
|
||||
return
|
||||
}
|
||||
;(cleanOptions as any)[key] = value
|
||||
}
|
||||
})
|
||||
|
||||
onSave(instanceName, cleanOptions)
|
||||
onOpenChange(false)
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
onOpenChange(false)
|
||||
}
|
||||
|
||||
const toggleAdvanced = () => {
|
||||
setShowAdvanced(!showAdvanced)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[600px] max-h-[80vh] overflow-hidden flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{isEditing ? 'Edit Instance' : 'Create New Instance'}
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
{isEditing
|
||||
? 'Modify the instance configuration below.'
|
||||
: 'Configure your new llama-server instance below.'}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
<div className="grid gap-6 py-4">
|
||||
{/* Instance Name - Special handling since it's not in CreateInstanceOptions */}
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="name">
|
||||
Instance Name <span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="name"
|
||||
value={instanceName}
|
||||
onChange={(e) => handleNameChange(e.target.value)}
|
||||
placeholder="my-instance"
|
||||
disabled={isEditing} // Don't allow name changes when editing
|
||||
className={nameError ? 'border-red-500' : ''}
|
||||
/>
|
||||
{nameError && (
|
||||
<p className="text-sm text-red-500">{nameError}</p>
|
||||
)}
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Unique identifier for the instance
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Basic Fields - Automatically generated from type */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-medium">Basic Configuration</h3>
|
||||
{basicFields.map((fieldKey) => (
|
||||
<ZodFormField
|
||||
key={fieldKey}
|
||||
fieldKey={fieldKey}
|
||||
value={formData[fieldKey]}
|
||||
onChange={handleFieldChange}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Advanced Fields Toggle */}
|
||||
<div className="border-t pt-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={toggleAdvanced}
|
||||
className="flex items-center gap-2 p-0 h-auto font-medium"
|
||||
>
|
||||
{showAdvanced ? (
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
) : (
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
)}
|
||||
Advanced Configuration
|
||||
<span className="text-muted-foreground text-sm font-normal">
|
||||
({advancedFields.length} options)
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Advanced Fields - Automatically generated from type */}
|
||||
{showAdvanced && (
|
||||
<div className="space-y-4 pl-6 border-l-2 border-muted">
|
||||
<div className="space-y-4">
|
||||
{advancedFields.sort().map((fieldKey) => (
|
||||
<ZodFormField
|
||||
key={fieldKey}
|
||||
fieldKey={fieldKey}
|
||||
value={formData[fieldKey]}
|
||||
onChange={handleFieldChange}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="pt-4 border-t">
|
||||
<Button variant="outline" onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleSave} disabled={!instanceName.trim() || !!nameError}>
|
||||
{isEditing ? 'Save Changes' : 'Create Instance'}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default InstanceModal
|
||||
119
ui/src/components/ZodFormField.tsx
Normal file
119
ui/src/components/ZodFormField.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
import React from 'react'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { CreateInstanceOptions } from '@/types/instance'
|
||||
import { getFieldType, basicFieldsConfig } from '@/lib/zodFormUtils'
|
||||
|
||||
interface ZodFormFieldProps {
|
||||
fieldKey: keyof CreateInstanceOptions
|
||||
value: any
|
||||
onChange: (key: keyof CreateInstanceOptions, value: any) => void
|
||||
}
|
||||
|
||||
const ZodFormField: React.FC<ZodFormFieldProps> = ({ fieldKey, value, onChange }) => {
|
||||
// Get configuration for basic fields, or use field name for advanced fields
|
||||
const config = basicFieldsConfig[fieldKey as string] || { label: fieldKey }
|
||||
|
||||
// Get type from Zod schema
|
||||
const fieldType = getFieldType(fieldKey)
|
||||
|
||||
const handleChange = (newValue: any) => {
|
||||
onChange(fieldKey, newValue)
|
||||
}
|
||||
|
||||
const renderField = () => {
|
||||
switch (fieldType) {
|
||||
case 'boolean':
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id={fieldKey}
|
||||
checked={value || false}
|
||||
onCheckedChange={(checked) => handleChange(checked)}
|
||||
/>
|
||||
<Label htmlFor={fieldKey} className="text-sm font-normal">
|
||||
{config.label}
|
||||
{config.description && (
|
||||
<span className="text-muted-foreground ml-1">- {config.description}</span>
|
||||
)}
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
|
||||
case 'number':
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor={fieldKey}>
|
||||
{config.label}
|
||||
{config.required && <span className="text-red-500 ml-1">*</span>}
|
||||
</Label>
|
||||
<Input
|
||||
id={fieldKey}
|
||||
type="number"
|
||||
value={value || ''}
|
||||
onChange={(e) => {
|
||||
const numValue = e.target.value ? parseFloat(e.target.value) : undefined
|
||||
handleChange(numValue)
|
||||
}}
|
||||
placeholder={config.placeholder}
|
||||
/>
|
||||
{config.description && (
|
||||
<p className="text-sm text-muted-foreground">{config.description}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
case 'array':
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor={fieldKey}>
|
||||
{config.label}
|
||||
{config.required && <span className="text-red-500 ml-1">*</span>}
|
||||
</Label>
|
||||
<Input
|
||||
id={fieldKey}
|
||||
type="text"
|
||||
value={Array.isArray(value) ? value.join(', ') : ''}
|
||||
onChange={(e) => {
|
||||
const arrayValue = e.target.value
|
||||
? e.target.value.split(',').map(s => s.trim()).filter(Boolean)
|
||||
: undefined
|
||||
handleChange(arrayValue)
|
||||
}}
|
||||
placeholder="item1, item2, item3"
|
||||
/>
|
||||
{config.description && (
|
||||
<p className="text-sm text-muted-foreground">{config.description}</p>
|
||||
)}
|
||||
<p className="text-xs text-muted-foreground">Separate multiple values with commas</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
case 'text':
|
||||
default:
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor={fieldKey}>
|
||||
{config.label}
|
||||
{config.required && <span className="text-red-500 ml-1">*</span>}
|
||||
</Label>
|
||||
<Input
|
||||
id={fieldKey}
|
||||
type="text"
|
||||
value={value || ''}
|
||||
onChange={(e) => handleChange(e.target.value || undefined)}
|
||||
placeholder={config.placeholder}
|
||||
/>
|
||||
{config.description && (
|
||||
<p className="text-sm text-muted-foreground">{config.description}</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return <div className="space-y-2">{renderField()}</div>
|
||||
}
|
||||
|
||||
export default ZodFormField
|
||||
30
ui/src/components/ui/checkbox.tsx
Normal file
30
ui/src/components/ui/checkbox.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import * as React from "react"
|
||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
||||
import { CheckIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Checkbox({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
||||
return (
|
||||
<CheckboxPrimitive.Root
|
||||
data-slot="checkbox"
|
||||
className={cn(
|
||||
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitive.Indicator
|
||||
data-slot="checkbox-indicator"
|
||||
className="flex items-center justify-center text-current transition-none"
|
||||
>
|
||||
<CheckIcon className="size-3.5" />
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export { Checkbox }
|
||||
141
ui/src/components/ui/dialog.tsx
Normal file
141
ui/src/components/ui/dialog.tsx
Normal file
@@ -0,0 +1,141 @@
|
||||
import * as React from "react"
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||
import { XIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Dialog({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
||||
return <DialogPrimitive.Root data-slot="dialog" {...props} />
|
||||
}
|
||||
|
||||
function DialogTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
||||
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
|
||||
}
|
||||
|
||||
function DialogPortal({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
||||
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
|
||||
}
|
||||
|
||||
function DialogClose({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
||||
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
|
||||
}
|
||||
|
||||
function DialogOverlay({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
||||
return (
|
||||
<DialogPrimitive.Overlay
|
||||
data-slot="dialog-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogContent({
|
||||
className,
|
||||
children,
|
||||
showCloseButton = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
||||
showCloseButton?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DialogPortal data-slot="dialog-portal">
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
{showCloseButton && (
|
||||
<DialogPrimitive.Close
|
||||
data-slot="dialog-close"
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||
>
|
||||
<XIcon />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
)}
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="dialog-header"
|
||||
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="dialog-footer"
|
||||
className={cn(
|
||||
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogTitle({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
||||
return (
|
||||
<DialogPrimitive.Title
|
||||
data-slot="dialog-title"
|
||||
className={cn("text-lg leading-none font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogDescription({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
||||
return (
|
||||
<DialogPrimitive.Description
|
||||
data-slot="dialog-description"
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
}
|
||||
21
ui/src/components/ui/input.tsx
Normal file
21
ui/src/components/ui/input.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
data-slot="input"
|
||||
className={cn(
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Input }
|
||||
22
ui/src/components/ui/label.tsx
Normal file
22
ui/src/components/ui/label.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import * as React from "react"
|
||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Label({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
||||
return (
|
||||
<LabelPrimitive.Root
|
||||
data-slot="label"
|
||||
className={cn(
|
||||
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Label }
|
||||
49
ui/src/lib/zodFormUtils.ts
Normal file
49
ui/src/lib/zodFormUtils.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { CreateInstanceOptions, getAllFieldKeys } from '@/schemas/instanceOptions'
|
||||
|
||||
// Only define the basic fields we want to show by default
|
||||
export const basicFieldsConfig: Record<string, {
|
||||
label: string
|
||||
description?: string
|
||||
placeholder?: string
|
||||
required?: boolean
|
||||
}> = {
|
||||
auto_restart: {
|
||||
label: 'Auto Restart',
|
||||
description: 'Automatically restart the instance on failure'
|
||||
},
|
||||
model: {
|
||||
label: 'Model Path',
|
||||
placeholder: '/path/to/model.gguf',
|
||||
description: 'Path to the model file'
|
||||
},
|
||||
hf_repo: {
|
||||
label: 'Hugging Face Repository',
|
||||
placeholder: 'microsoft/DialoGPT-medium',
|
||||
description: 'Hugging Face model repository'
|
||||
},
|
||||
hf_file: {
|
||||
label: 'Hugging Face File',
|
||||
placeholder: 'model.gguf',
|
||||
description: 'Specific file in the repository'
|
||||
},
|
||||
gpu_layers: {
|
||||
label: 'GPU Layers',
|
||||
placeholder: '0',
|
||||
description: 'Number of layers to offload to GPU'
|
||||
}
|
||||
}
|
||||
|
||||
export function isBasicField(key: keyof CreateInstanceOptions): boolean {
|
||||
return key in basicFieldsConfig
|
||||
}
|
||||
|
||||
export function getBasicFields(): (keyof CreateInstanceOptions)[] {
|
||||
return Object.keys(basicFieldsConfig) as (keyof CreateInstanceOptions)[]
|
||||
}
|
||||
|
||||
export function getAdvancedFields(): (keyof CreateInstanceOptions)[] {
|
||||
return getAllFieldKeys().filter(key => !isBasicField(key))
|
||||
}
|
||||
|
||||
// Re-export the Zod-based functions
|
||||
export { getFieldType } from '@/schemas/instanceOptions'
|
||||
199
ui/src/schemas/instanceOptions.ts
Normal file
199
ui/src/schemas/instanceOptions.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
// Define the Zod schema
|
||||
export const CreateInstanceOptionsSchema = z.object({
|
||||
// Restart options
|
||||
auto_restart: z.boolean().optional(),
|
||||
max_restarts: z.number().optional(),
|
||||
restart_delay: z.number().optional(),
|
||||
|
||||
// Common params
|
||||
verbose_prompt: z.boolean().optional(),
|
||||
threads: z.number().optional(),
|
||||
threads_batch: z.number().optional(),
|
||||
cpu_mask: z.string().optional(),
|
||||
cpu_range: z.string().optional(),
|
||||
cpu_strict: z.number().optional(),
|
||||
priority: z.number().optional(),
|
||||
poll: z.number().optional(),
|
||||
cpu_mask_batch: z.string().optional(),
|
||||
cpu_range_batch: z.string().optional(),
|
||||
cpu_strict_batch: z.number().optional(),
|
||||
priority_batch: z.number().optional(),
|
||||
poll_batch: z.number().optional(),
|
||||
ctx_size: z.number().optional(),
|
||||
predict: z.number().optional(),
|
||||
batch_size: z.number().optional(),
|
||||
ubatch_size: z.number().optional(),
|
||||
keep: z.number().optional(),
|
||||
flash_attn: z.boolean().optional(),
|
||||
no_perf: z.boolean().optional(),
|
||||
escape: z.boolean().optional(),
|
||||
no_escape: z.boolean().optional(),
|
||||
rope_scaling: z.string().optional(),
|
||||
rope_scale: z.number().optional(),
|
||||
rope_freq_base: z.number().optional(),
|
||||
rope_freq_scale: z.number().optional(),
|
||||
yarn_orig_ctx: z.number().optional(),
|
||||
yarn_ext_factor: z.number().optional(),
|
||||
yarn_attn_factor: z.number().optional(),
|
||||
yarn_beta_slow: z.number().optional(),
|
||||
yarn_beta_fast: z.number().optional(),
|
||||
dump_kv_cache: z.boolean().optional(),
|
||||
no_kv_offload: z.boolean().optional(),
|
||||
cache_type_k: z.string().optional(),
|
||||
cache_type_v: z.string().optional(),
|
||||
defrag_thold: z.number().optional(),
|
||||
parallel: z.number().optional(),
|
||||
mlock: z.boolean().optional(),
|
||||
no_mmap: z.boolean().optional(),
|
||||
numa: z.string().optional(),
|
||||
device: z.string().optional(),
|
||||
override_tensor: z.array(z.string()).optional(),
|
||||
gpu_layers: z.number().optional(),
|
||||
split_mode: z.string().optional(),
|
||||
tensor_split: z.string().optional(),
|
||||
main_gpu: z.number().optional(),
|
||||
check_tensors: z.boolean().optional(),
|
||||
override_kv: z.array(z.string()).optional(),
|
||||
lora: z.array(z.string()).optional(),
|
||||
lora_scaled: z.array(z.string()).optional(),
|
||||
control_vector: z.array(z.string()).optional(),
|
||||
control_vector_scaled: z.array(z.string()).optional(),
|
||||
control_vector_layer_range: z.string().optional(),
|
||||
model: z.string().optional(),
|
||||
model_url: z.string().optional(),
|
||||
hf_repo: z.string().optional(),
|
||||
hf_repo_draft: z.string().optional(),
|
||||
hf_file: z.string().optional(),
|
||||
hf_repo_v: z.string().optional(),
|
||||
hf_file_v: z.string().optional(),
|
||||
hf_token: z.string().optional(),
|
||||
log_disable: z.boolean().optional(),
|
||||
log_file: z.string().optional(),
|
||||
log_colors: z.boolean().optional(),
|
||||
verbose: z.boolean().optional(),
|
||||
verbosity: z.number().optional(),
|
||||
log_prefix: z.boolean().optional(),
|
||||
log_timestamps: z.boolean().optional(),
|
||||
|
||||
// Sampling params
|
||||
samplers: z.string().optional(),
|
||||
seed: z.number().optional(),
|
||||
sampling_seq: z.string().optional(),
|
||||
ignore_eos: z.boolean().optional(),
|
||||
temperature: z.number().optional(),
|
||||
top_k: z.number().optional(),
|
||||
top_p: z.number().optional(),
|
||||
min_p: z.number().optional(),
|
||||
xtc_probability: z.number().optional(),
|
||||
xtc_threshold: z.number().optional(),
|
||||
typical: z.number().optional(),
|
||||
repeat_last_n: z.number().optional(),
|
||||
repeat_penalty: z.number().optional(),
|
||||
presence_penalty: z.number().optional(),
|
||||
frequency_penalty: z.number().optional(),
|
||||
dry_multiplier: z.number().optional(),
|
||||
dry_base: z.number().optional(),
|
||||
dry_allowed_length: z.number().optional(),
|
||||
dry_penalty_last_n: z.number().optional(),
|
||||
dry_sequence_breaker: z.array(z.string()).optional(),
|
||||
dynatemp_range: z.number().optional(),
|
||||
dynatemp_exp: z.number().optional(),
|
||||
mirostat: z.number().optional(),
|
||||
mirostat_lr: z.number().optional(),
|
||||
mirostat_ent: z.number().optional(),
|
||||
logit_bias: z.array(z.string()).optional(),
|
||||
grammar: z.string().optional(),
|
||||
grammar_file: z.string().optional(),
|
||||
json_schema: z.string().optional(),
|
||||
json_schema_file: z.string().optional(),
|
||||
|
||||
// Server/Example-specific params
|
||||
no_context_shift: z.boolean().optional(),
|
||||
special: z.boolean().optional(),
|
||||
no_warmup: z.boolean().optional(),
|
||||
spm_infill: z.boolean().optional(),
|
||||
pooling: z.string().optional(),
|
||||
cont_batching: z.boolean().optional(),
|
||||
no_cont_batching: z.boolean().optional(),
|
||||
mmproj: z.string().optional(),
|
||||
mmproj_url: z.string().optional(),
|
||||
no_mmproj: z.boolean().optional(),
|
||||
no_mmproj_offload: z.boolean().optional(),
|
||||
alias: z.string().optional(),
|
||||
host: z.string().optional(),
|
||||
port: z.number().optional(),
|
||||
path: z.string().optional(),
|
||||
no_webui: z.boolean().optional(),
|
||||
embedding: z.boolean().optional(),
|
||||
reranking: z.boolean().optional(),
|
||||
api_key: z.string().optional(),
|
||||
api_key_file: z.string().optional(),
|
||||
ssl_key_file: z.string().optional(),
|
||||
ssl_cert_file: z.string().optional(),
|
||||
chat_template_kwargs: z.string().optional(),
|
||||
timeout: z.number().optional(),
|
||||
threads_http: z.number().optional(),
|
||||
cache_reuse: z.number().optional(),
|
||||
metrics: z.boolean().optional(),
|
||||
slots: z.boolean().optional(),
|
||||
props: z.boolean().optional(),
|
||||
no_slots: z.boolean().optional(),
|
||||
slot_save_path: z.string().optional(),
|
||||
jinja: z.boolean().optional(),
|
||||
reasoning_format: z.string().optional(),
|
||||
reasoning_budget: z.number().optional(),
|
||||
chat_template: z.string().optional(),
|
||||
chat_template_file: z.string().optional(),
|
||||
no_prefill_assistant: z.boolean().optional(),
|
||||
slot_prompt_similarity: z.number().optional(),
|
||||
lora_init_without_apply: z.boolean().optional(),
|
||||
|
||||
// Speculative decoding params
|
||||
draft_max: z.number().optional(),
|
||||
draft_min: z.number().optional(),
|
||||
draft_p_min: z.number().optional(),
|
||||
ctx_size_draft: z.number().optional(),
|
||||
device_draft: z.string().optional(),
|
||||
gpu_layers_draft: z.number().optional(),
|
||||
model_draft: z.string().optional(),
|
||||
cache_type_k_draft: z.string().optional(),
|
||||
cache_type_v_draft: z.string().optional(),
|
||||
|
||||
// Audio/TTS params
|
||||
model_vocoder: z.string().optional(),
|
||||
tts_use_guide_tokens: z.boolean().optional(),
|
||||
|
||||
// Default model params
|
||||
embd_bge_small_en_default: z.boolean().optional(),
|
||||
embd_e5_small_en_default: z.boolean().optional(),
|
||||
embd_gte_small_default: z.boolean().optional(),
|
||||
fim_qwen_1_5b_default: z.boolean().optional(),
|
||||
fim_qwen_3b_default: z.boolean().optional(),
|
||||
fim_qwen_7b_default: z.boolean().optional(),
|
||||
fim_qwen_7b_spec: z.boolean().optional(),
|
||||
fim_qwen_14b_spec: z.boolean().optional(),
|
||||
})
|
||||
|
||||
// Infer the TypeScript type from the schema
|
||||
export type CreateInstanceOptions = z.infer<typeof CreateInstanceOptionsSchema>
|
||||
|
||||
// Helper to get all field keys
|
||||
export function getAllFieldKeys(): (keyof CreateInstanceOptions)[] {
|
||||
return Object.keys(CreateInstanceOptionsSchema.shape) as (keyof CreateInstanceOptions)[]
|
||||
}
|
||||
|
||||
// Get field type from Zod schema
|
||||
export function getFieldType(key: keyof CreateInstanceOptions): 'text' | 'number' | 'boolean' | 'array' {
|
||||
const fieldSchema = CreateInstanceOptionsSchema.shape[key]
|
||||
if (!fieldSchema) return 'text'
|
||||
|
||||
// Handle ZodOptional wrapper
|
||||
const innerSchema = fieldSchema instanceof z.ZodOptional ? fieldSchema.unwrap() : fieldSchema
|
||||
|
||||
if (innerSchema instanceof z.ZodBoolean) return 'boolean'
|
||||
if (innerSchema instanceof z.ZodNumber) return 'number'
|
||||
if (innerSchema instanceof z.ZodArray) return 'array'
|
||||
return 'text' // ZodString and others default to text
|
||||
}
|
||||
@@ -1,181 +1,9 @@
|
||||
import { CreateInstanceOptions } from '@/schemas/instanceOptions'
|
||||
|
||||
export { type CreateInstanceOptions } from '@/schemas/instanceOptions'
|
||||
|
||||
export interface Instance {
|
||||
name: string;
|
||||
running: boolean;
|
||||
options?: CreateInstanceOptions;
|
||||
}
|
||||
|
||||
export interface CreateInstanceOptions {
|
||||
|
||||
auto_restart?: boolean;
|
||||
max_restarts?: number;
|
||||
restart_delay?: number;
|
||||
|
||||
// Llama server options
|
||||
// Common params
|
||||
verbose_prompt?: boolean;
|
||||
threads?: number;
|
||||
threads_batch?: number;
|
||||
cpu_mask?: string;
|
||||
cpu_range?: string;
|
||||
cpu_strict?: number;
|
||||
priority?: number;
|
||||
poll?: number;
|
||||
cpu_mask_batch?: string;
|
||||
cpu_range_batch?: string;
|
||||
cpu_strict_batch?: number;
|
||||
priority_batch?: number;
|
||||
poll_batch?: number;
|
||||
ctx_size?: number;
|
||||
predict?: number;
|
||||
batch_size?: number;
|
||||
ubatch_size?: number;
|
||||
keep?: number;
|
||||
flash_attn?: boolean;
|
||||
no_perf?: boolean;
|
||||
escape?: boolean;
|
||||
no_escape?: boolean;
|
||||
rope_scaling?: string;
|
||||
rope_scale?: number;
|
||||
rope_freq_base?: number;
|
||||
rope_freq_scale?: number;
|
||||
yarn_orig_ctx?: number;
|
||||
yarn_ext_factor?: number;
|
||||
yarn_attn_factor?: number;
|
||||
yarn_beta_slow?: number;
|
||||
yarn_beta_fast?: number;
|
||||
dump_kv_cache?: boolean;
|
||||
no_kv_offload?: boolean;
|
||||
cache_type_k?: string;
|
||||
cache_type_v?: string;
|
||||
defrag_thold?: number;
|
||||
parallel?: number;
|
||||
mlock?: boolean;
|
||||
no_mmap?: boolean;
|
||||
numa?: string;
|
||||
device?: string;
|
||||
override_tensor?: string[];
|
||||
gpu_layers?: number;
|
||||
split_mode?: string;
|
||||
tensor_split?: string;
|
||||
main_gpu?: number;
|
||||
check_tensors?: boolean;
|
||||
override_kv?: string[];
|
||||
lora?: string[];
|
||||
lora_scaled?: string[];
|
||||
control_vector?: string[];
|
||||
control_vector_scaled?: string[];
|
||||
control_vector_layer_range?: string;
|
||||
model?: string;
|
||||
model_url?: string;
|
||||
hf_repo?: string;
|
||||
hf_repo_draft?: string;
|
||||
hf_file?: string;
|
||||
hf_repo_v?: string;
|
||||
hf_file_v?: string;
|
||||
hf_token?: string;
|
||||
log_disable?: boolean;
|
||||
log_file?: string;
|
||||
log_colors?: boolean;
|
||||
verbose?: boolean;
|
||||
verbosity?: number;
|
||||
log_prefix?: boolean;
|
||||
log_timestamps?: boolean;
|
||||
|
||||
// Sampling params
|
||||
samplers?: string;
|
||||
seed?: number;
|
||||
sampling_seq?: string;
|
||||
ignore_eos?: boolean;
|
||||
temperature?: number;
|
||||
top_k?: number;
|
||||
top_p?: number;
|
||||
min_p?: number;
|
||||
xtc_probability?: number;
|
||||
xtc_threshold?: number;
|
||||
typical?: number;
|
||||
repeat_last_n?: number;
|
||||
repeat_penalty?: number;
|
||||
presence_penalty?: number;
|
||||
frequency_penalty?: number;
|
||||
dry_multiplier?: number;
|
||||
dry_base?: number;
|
||||
dry_allowed_length?: number;
|
||||
dry_penalty_last_n?: number;
|
||||
dry_sequence_breaker?: string[];
|
||||
dynatemp_range?: number;
|
||||
dynatemp_exp?: number;
|
||||
mirostat?: number;
|
||||
mirostat_lr?: number;
|
||||
mirostat_ent?: number;
|
||||
logit_bias?: string[];
|
||||
grammar?: string;
|
||||
grammar_file?: string;
|
||||
json_schema?: string;
|
||||
json_schema_file?: string;
|
||||
|
||||
// Server/Example-specific params
|
||||
no_context_shift?: boolean;
|
||||
special?: boolean;
|
||||
no_warmup?: boolean;
|
||||
spm_infill?: boolean;
|
||||
pooling?: string;
|
||||
cont_batching?: boolean;
|
||||
no_cont_batching?: boolean;
|
||||
mmproj?: string;
|
||||
mmproj_url?: string;
|
||||
no_mmproj?: boolean;
|
||||
no_mmproj_offload?: boolean;
|
||||
alias?: string;
|
||||
host?: string;
|
||||
port?: number;
|
||||
path?: string;
|
||||
no_webui?: boolean;
|
||||
embedding?: boolean;
|
||||
reranking?: boolean;
|
||||
api_key?: string;
|
||||
api_key_file?: string;
|
||||
ssl_key_file?: string;
|
||||
ssl_cert_file?: string;
|
||||
chat_template_kwargs?: string;
|
||||
timeout?: number;
|
||||
threads_http?: number;
|
||||
cache_reuse?: number;
|
||||
metrics?: boolean;
|
||||
slots?: boolean;
|
||||
props?: boolean;
|
||||
no_slots?: boolean;
|
||||
slot_save_path?: string;
|
||||
jinja?: boolean;
|
||||
reasoning_format?: string;
|
||||
reasoning_budget?: number;
|
||||
chat_template?: string;
|
||||
chat_template_file?: string;
|
||||
no_prefill_assistant?: boolean;
|
||||
slot_prompt_similarity?: number;
|
||||
lora_init_without_apply?: boolean;
|
||||
|
||||
// Speculative decoding params
|
||||
draft_max?: number;
|
||||
draft_min?: number;
|
||||
draft_p_min?: number;
|
||||
ctx_size_draft?: number;
|
||||
device_draft?: string;
|
||||
gpu_layers_draft?: number;
|
||||
model_draft?: string;
|
||||
cache_type_k_draft?: string;
|
||||
cache_type_v_draft?: string;
|
||||
|
||||
// Audio/TTS params
|
||||
model_vocoder?: string;
|
||||
tts_use_guide_tokens?: boolean;
|
||||
|
||||
// Default model params
|
||||
embd_bge_small_en_default?: boolean;
|
||||
embd_e5_small_en_default?: boolean;
|
||||
embd_gte_small_default?: boolean;
|
||||
fim_qwen_1_5b_default?: boolean;
|
||||
fim_qwen_3b_default?: boolean;
|
||||
fim_qwen_7b_default?: boolean;
|
||||
fim_qwen_7b_spec?: boolean;
|
||||
fim_qwen_14b_spec?: boolean;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user