mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-29 04:45:13 +08:00
🔥 Sync 2026-09-05 21:18:46
This commit is contained in:
1 parent
e88d0b9fed
commit
b05ff8a1b6
45 files changed
+506
-272
No files matched your search
+15
-2
@@ -15,7 +15,7 @@ AGENTFLOW_HASH_aarch64:=6d733ebc49b095bf8670a1b655a13bb8ad98c90ced19701b67d5cdd4
|
||||
|
||||
PKG_NAME:=agentflow
|
||||
PKG_VERSION:=0.3.0
|
||||
PKG_RELEASE:=6
|
||||
PKG_RELEASE:=7
|
||||
|
||||
AGENTFLOW_URL_FILE:=agentflow-linux-$(AGENTFLOW_ARCH)
|
||||
AGENTFLOW_DOWNLOAD:=$(AGENTFLOW_URL_FILE)-$(AGENTFLOW_HASH_$(ARCH))
|
||||
@@ -52,6 +52,16 @@ define Package/$(PKG_NAME)/conffiles
|
||||
/etc/config/agentflow
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/prerm
|
||||
#!/bin/sh
|
||||
if [ "$${IPKG_INSTROOT}" = "" ]; then
|
||||
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/30-agentflow.json 2>/dev/null)" = "/usr/share/agentflow/agentflow-plugin.json" ]; then
|
||||
rm -f /usr/share/linkeasefull/desktop-apps.d/30-agentflow.json
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(INSTALL_DIR) $(PKG_BUILD_DIR)
|
||||
$(CP) $(DL_DIR)/$(AGENTFLOW_DOWNLOAD) $(PKG_BUILD_DIR)/agentflow
|
||||
@@ -64,11 +74,14 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config $(1)/usr/share/agentflow/www $(1)/usr/share/linkeasefull/desktop-apps.d
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/agentflow $(1)/usr/sbin/agentflow
|
||||
$(INSTALL_BIN) ./files/agentflow.init $(1)/etc/init.d/agentflow
|
||||
$(INSTALL_BIN) ./files/agentflow.uci-default $(1)/etc/uci-defaults/09-agentflow
|
||||
$(INSTALL_CONF) ./files/agentflow.config $(1)/etc/config/agentflow
|
||||
$(INSTALL_DATA) ./files/agentflow-plugin.json $(1)/usr/share/agentflow/agentflow-plugin.json
|
||||
$(INSTALL_DATA) ./files/www/logo.svg $(1)/usr/share/agentflow/www/logo.svg
|
||||
ln -sf /usr/share/agentflow/agentflow-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/30-agentflow.json
|
||||
endef
|
||||
|
||||
$(eval $(call Download,agentflow))
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "agentflow",
|
||||
"name": "AgentFlow",
|
||||
"icon": "logo.svg",
|
||||
"staticRoot": "/usr/share/agentflow/www",
|
||||
"desktop": {
|
||||
"mode": "module",
|
||||
"entry": "desktop-entry.js",
|
||||
"isolation": "shadow-dom"
|
||||
},
|
||||
"standalone": {
|
||||
"entry": "index.html",
|
||||
"basePath": "/apps/agentflow/",
|
||||
"url": "/cgi-bin/luci/admin/services/agentflow/open",
|
||||
"externalOpen": {
|
||||
"enabled": true,
|
||||
"label": "Open AgentFlow"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"mode": "passthrough"
|
||||
},
|
||||
"backend": {
|
||||
"type": "http",
|
||||
"scheme": "http",
|
||||
"host": "127.0.0.1",
|
||||
"portFromUci": "agentflow.@agentflow[0].port",
|
||||
"defaultPort": 9000,
|
||||
"upstreamBasePath": "/apps/agentflow/",
|
||||
"pathMode": "preserve",
|
||||
"proxyMode": "app-base"
|
||||
},
|
||||
"window": {
|
||||
"width": 1180,
|
||||
"height": 760,
|
||||
"singleton": true
|
||||
},
|
||||
"capabilities": ["agent", "coding", "workflow"],
|
||||
"categories": ["development", "ai"]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<svg
|
||||
width="150"
|
||||
height="150"
|
||||
viewBox="0 0 150 150"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="150" height="150" rx="30" fill="#f5f1e8" />
|
||||
<text
|
||||
x="50%"
|
||||
y="54%"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="68"
|
||||
font-weight="700"
|
||||
font-family="Georgia, 'Times New Roman', serif"
|
||||
letter-spacing="-4"
|
||||
fill="#111111"
|
||||
>
|
||||
AF
|
||||
</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 408 B |
@@ -0,0 +1,48 @@
|
||||
import json
|
||||
import pathlib
|
||||
import unittest
|
||||
|
||||
|
||||
APP_DIR = pathlib.Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
class DesktopManifestContractTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.manifest = json.loads(
|
||||
(APP_DIR / "files" / "agentflow-plugin.json").read_text()
|
||||
)
|
||||
|
||||
def test_manifest_uses_agentflow_app_base_proxy(self):
|
||||
self.assertEqual(self.manifest["id"], "agentflow")
|
||||
self.assertEqual(self.manifest["staticRoot"], "/usr/share/agentflow/www")
|
||||
self.assertEqual(self.manifest["standalone"]["entry"], "index.html")
|
||||
self.assertEqual(self.manifest["standalone"]["basePath"], "/apps/agentflow/")
|
||||
self.assertEqual(
|
||||
self.manifest["standalone"]["url"],
|
||||
"/cgi-bin/luci/admin/services/agentflow/open",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.manifest["standalone"]["externalOpen"],
|
||||
{"enabled": True, "label": "Open AgentFlow"},
|
||||
)
|
||||
self.assertEqual(self.manifest["auth"]["mode"], "passthrough")
|
||||
|
||||
backend = self.manifest["backend"]
|
||||
self.assertEqual(backend["upstreamBasePath"], "/apps/agentflow/")
|
||||
self.assertEqual(backend["pathMode"], "preserve")
|
||||
self.assertEqual(backend["proxyMode"], "app-base")
|
||||
|
||||
def test_desktop_entry_matches_manifest_contract(self):
|
||||
desktop = self.manifest["desktop"]
|
||||
self.assertEqual(desktop["mode"], "module")
|
||||
self.assertEqual(desktop["entry"], "desktop-entry.js")
|
||||
self.assertEqual(desktop["isolation"], "shadow-dom")
|
||||
|
||||
self.assertFalse(
|
||||
(APP_DIR / "files" / "www" / "desktop-entry.js").exists(),
|
||||
"desktop-entry.js must be served by AgentFlow backend, not the static iframe wrapper",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -2,12 +2,27 @@ from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
APPLICATIONS = ROOT / "applications"
|
||||
THIS_FILE = Path(__file__).resolve()
|
||||
|
||||
|
||||
def read(relative):
|
||||
return (APPLICATIONS / relative).read_text()
|
||||
relative_path = Path(relative)
|
||||
package = relative_path.parts[0]
|
||||
app = package[9:] if package.startswith("luci-app-") else package
|
||||
remainder = Path(*relative_path.parts[1:])
|
||||
|
||||
candidates = [
|
||||
THIS_FILE.parents[index] / relative_path
|
||||
for index in range(2, min(len(THIS_FILE.parents), 6))
|
||||
]
|
||||
candidates.append(THIS_FILE.parents[3] / app / package / remainder)
|
||||
|
||||
for candidate in candidates:
|
||||
if candidate.exists():
|
||||
return candidate.read_text()
|
||||
|
||||
searched = "\n".join(str(candidate) for candidate in candidates)
|
||||
raise FileNotFoundError(f"{relative} not found; searched:\n{searched}")
|
||||
|
||||
|
||||
class MiseRuntimeContractTest(unittest.TestCase):
|
||||
|
||||
Reference in new issue
Block a user