@agentunion/kite 1.0.7 → 1.3.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/CHANGELOG.md +208 -0
- package/README.md +48 -0
- package/cli.js +1 -1
- package/extensions/agents/__init__.py +1 -0
- package/extensions/agents/assistant/__init__.py +1 -0
- package/extensions/agents/assistant/entry.py +329 -0
- package/extensions/agents/assistant/module.md +22 -0
- package/extensions/agents/assistant/server.py +197 -0
- package/extensions/channels/__init__.py +1 -0
- package/extensions/channels/acp_channel/__init__.py +1 -0
- package/extensions/channels/acp_channel/entry.py +329 -0
- package/extensions/channels/acp_channel/module.md +22 -0
- package/extensions/channels/acp_channel/server.py +197 -0
- package/extensions/event_hub_bench/entry.py +624 -379
- package/extensions/event_hub_bench/module.md +2 -1
- package/extensions/services/backup/__init__.py +1 -0
- package/extensions/services/backup/entry.py +508 -0
- package/extensions/services/backup/module.md +22 -0
- package/extensions/services/model_service/__init__.py +1 -0
- package/extensions/services/model_service/entry.py +508 -0
- package/extensions/services/model_service/module.md +22 -0
- package/extensions/services/watchdog/entry.py +468 -102
- package/extensions/services/watchdog/module.md +3 -0
- package/extensions/services/watchdog/monitor.py +170 -69
- package/extensions/services/web/__init__.py +1 -0
- package/extensions/services/web/config.yaml +149 -0
- package/extensions/services/web/entry.py +390 -0
- package/extensions/services/web/module.md +24 -0
- package/extensions/services/web/routes/__init__.py +1 -0
- package/extensions/services/web/routes/routes_call.py +189 -0
- package/extensions/services/web/routes/routes_config.py +512 -0
- package/extensions/services/web/routes/routes_contacts.py +98 -0
- package/extensions/services/web/routes/routes_devlog.py +99 -0
- package/extensions/services/web/routes/routes_phone.py +81 -0
- package/extensions/services/web/routes/routes_sms.py +48 -0
- package/extensions/services/web/routes/routes_stats.py +17 -0
- package/extensions/services/web/routes/routes_voicechat.py +554 -0
- package/extensions/services/web/routes/schemas.py +216 -0
- package/extensions/services/web/server.py +375 -0
- package/extensions/services/web/static/css/style.css +1064 -0
- package/extensions/services/web/static/index.html +1445 -0
- package/extensions/services/web/static/js/app.js +4671 -0
- package/extensions/services/web/vendor/__init__.py +1 -0
- package/extensions/services/web/vendor/bluetooth/audio.py +348 -0
- package/extensions/services/web/vendor/bluetooth/contacts.py +251 -0
- package/extensions/services/web/vendor/bluetooth/manager.py +395 -0
- package/extensions/services/web/vendor/bluetooth/sms.py +290 -0
- package/extensions/services/web/vendor/bluetooth/telephony.py +274 -0
- package/extensions/services/web/vendor/config.py +139 -0
- package/extensions/services/web/vendor/conversation/asr.py +936 -0
- package/extensions/services/web/vendor/conversation/engine.py +548 -0
- package/extensions/services/web/vendor/conversation/llm.py +534 -0
- package/extensions/services/web/vendor/conversation/mcp_tools.py +190 -0
- package/extensions/services/web/vendor/conversation/tts.py +322 -0
- package/extensions/services/web/vendor/conversation/vad.py +138 -0
- package/extensions/services/web/vendor/storage/__init__.py +1 -0
- package/extensions/services/web/vendor/storage/identity.py +312 -0
- package/extensions/services/web/vendor/storage/store.py +507 -0
- package/extensions/services/web/vendor/task/manager.py +864 -0
- package/extensions/services/web/vendor/task/models.py +45 -0
- package/extensions/services/web/vendor/task/webhook.py +263 -0
- package/extensions/services/web/vendor/tools/registry.py +321 -0
- package/kernel/__init__.py +0 -0
- package/kernel/entry.py +407 -0
- package/{core/event_hub/hub.py → kernel/event_hub.py} +62 -74
- package/kernel/module.md +33 -0
- package/{core/registry/store.py → kernel/registry_store.py} +23 -8
- package/kernel/rpc_router.py +388 -0
- package/kernel/server.py +267 -0
- package/launcher/__init__.py +10 -0
- package/launcher/__main__.py +6 -0
- package/launcher/count_lines.py +258 -0
- package/launcher/entry.py +1778 -0
- package/launcher/logging_setup.py +289 -0
- package/{core/launcher → launcher}/module_scanner.py +11 -6
- package/launcher/process_manager.py +880 -0
- package/main.py +11 -210
- package/package.json +6 -9
- package/__init__.py +0 -1
- package/__main__.py +0 -15
- package/core/event_hub/BENCHMARK.md +0 -94
- package/core/event_hub/bench.py +0 -459
- package/core/event_hub/bench_extreme.py +0 -308
- package/core/event_hub/bench_perf.py +0 -350
- package/core/event_hub/entry.py +0 -157
- package/core/event_hub/module.md +0 -20
- package/core/event_hub/server.py +0 -206
- package/core/launcher/entry.py +0 -1158
- package/core/launcher/process_manager.py +0 -470
- package/core/registry/entry.py +0 -110
- package/core/registry/module.md +0 -30
- package/core/registry/server.py +0 -289
- package/extensions/services/watchdog/server.py +0 -167
- /package/{core → extensions/services/web/vendor/bluetooth}/__init__.py +0 -0
- /package/{core/event_hub → extensions/services/web/vendor/conversation}/__init__.py +0 -0
- /package/{core/launcher → extensions/services/web/vendor/task}/__init__.py +0 -0
- /package/{core/registry → extensions/services/web/vendor/tools}/__init__.py +0 -0
- /package/{core/event_hub → kernel}/dedup.py +0 -0
- /package/{core/event_hub → kernel}/router.py +0 -0
- /package/{core/launcher → launcher}/module.md +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Routes for development log management."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException, Query
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from routes.schemas import (
|
|
11
|
+
DevLogCreate,
|
|
12
|
+
DevLogRecord,
|
|
13
|
+
DevLogUpdate,
|
|
14
|
+
PaginatedResponse,
|
|
15
|
+
)
|
|
16
|
+
from vendor.storage import store
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
router = APIRouter(tags=["devlog"])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@router.get("/devlog", response_model=PaginatedResponse)
|
|
24
|
+
async def list_devlog(
|
|
25
|
+
page: int = Query(1, ge=1),
|
|
26
|
+
page_size: int = Query(20, ge=1, le=200),
|
|
27
|
+
status: str | None = Query(None),
|
|
28
|
+
):
|
|
29
|
+
items, total = await store.list_devlog(page=page, page_size=page_size, status=status)
|
|
30
|
+
return PaginatedResponse(items=items, total=total, page=page, page_size=page_size)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@router.post("/devlog", response_model=DevLogRecord)
|
|
34
|
+
async def add_devlog(req: DevLogCreate):
|
|
35
|
+
data = req.model_dump(exclude_none=True)
|
|
36
|
+
record = await store.add_devlog(data)
|
|
37
|
+
return DevLogRecord(**record)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# --- Archive routes (must be before {record_id} to avoid path conflicts) ---
|
|
41
|
+
|
|
42
|
+
class ArchiveRequest(BaseModel):
|
|
43
|
+
cutoff: str | None = None # ISO-8601 datetime string
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@router.post("/devlog/archive")
|
|
47
|
+
async def archive_devlog(req: ArchiveRequest | None = None):
|
|
48
|
+
cutoff = req.cutoff if req else None
|
|
49
|
+
result = await store.archive_devlog(cutoff_iso=cutoff)
|
|
50
|
+
return result
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@router.get("/devlog/archives")
|
|
54
|
+
async def list_devlog_archives():
|
|
55
|
+
dates = await store.list_devlog_archives()
|
|
56
|
+
return {"dates": dates}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@router.get("/devlog/archive/last-cutoff")
|
|
60
|
+
async def get_last_archive_cutoff():
|
|
61
|
+
cutoff = await store.get_last_archive_cutoff()
|
|
62
|
+
return {"last_cutoff": cutoff}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@router.get("/devlog/archives/{date_str}")
|
|
66
|
+
async def read_devlog_archive(date_str: str):
|
|
67
|
+
records = await store.read_devlog_archive(date_str)
|
|
68
|
+
return {"date": date_str, "records": records}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# --- Single record routes ---
|
|
72
|
+
|
|
73
|
+
@router.get("/devlog/{record_id}", response_model=DevLogRecord)
|
|
74
|
+
async def get_devlog(record_id: str):
|
|
75
|
+
record = await store.get_devlog(record_id)
|
|
76
|
+
if record is None:
|
|
77
|
+
raise HTTPException(status_code=404, detail="Dev log not found")
|
|
78
|
+
return DevLogRecord(**record)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@router.put("/devlog/{record_id}", response_model=DevLogRecord)
|
|
82
|
+
async def update_devlog(record_id: str, updates: DevLogUpdate):
|
|
83
|
+
existing = await store.get_devlog(record_id)
|
|
84
|
+
if existing is None:
|
|
85
|
+
raise HTTPException(status_code=404, detail="Dev log not found")
|
|
86
|
+
update_data = updates.model_dump(exclude_none=True)
|
|
87
|
+
if not update_data:
|
|
88
|
+
raise HTTPException(status_code=400, detail="No fields to update")
|
|
89
|
+
await store.update_devlog(record_id, update_data)
|
|
90
|
+
updated = await store.get_devlog(record_id)
|
|
91
|
+
return DevLogRecord(**updated)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@router.delete("/devlog/{record_id}")
|
|
95
|
+
async def delete_devlog(record_id: str):
|
|
96
|
+
success = await store.delete_devlog(record_id)
|
|
97
|
+
if not success:
|
|
98
|
+
raise HTTPException(status_code=404, detail="Dev log not found")
|
|
99
|
+
return {"status": "deleted", "id": record_id}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Routes for phone / Bluetooth management."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
8
|
+
|
|
9
|
+
from routes.schemas import PhoneStatus
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
router = APIRouter(tags=["phone"])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@router.get("/phone/status", response_model=PhoneStatus)
|
|
17
|
+
async def phone_status(request: Request):
|
|
18
|
+
"""Return the current Bluetooth / phone connection status."""
|
|
19
|
+
bt: object = request.app.state.bt_manager
|
|
20
|
+
try:
|
|
21
|
+
status = bt.get_status() # sync method
|
|
22
|
+
return PhoneStatus(
|
|
23
|
+
bluetooth_connected=status.get("connected", False),
|
|
24
|
+
device_name=status.get("device_name"),
|
|
25
|
+
device_address=status.get("device_address"),
|
|
26
|
+
battery_level=status.get("battery_level"),
|
|
27
|
+
signal_strength=status.get("signal_strength"),
|
|
28
|
+
operator=status.get("operator_name"),
|
|
29
|
+
in_call=status.get("in_call", False),
|
|
30
|
+
)
|
|
31
|
+
except Exception as exc:
|
|
32
|
+
logger.exception("Failed to get phone status")
|
|
33
|
+
raise HTTPException(status_code=500, detail=str(exc))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@router.get("/phone/devices")
|
|
37
|
+
async def list_devices(request: Request):
|
|
38
|
+
"""Scan for nearby Bluetooth devices."""
|
|
39
|
+
bt = request.app.state.bt_manager
|
|
40
|
+
try:
|
|
41
|
+
devices = await bt.scan_devices()
|
|
42
|
+
return {"devices": devices}
|
|
43
|
+
except Exception as exc:
|
|
44
|
+
logger.exception("Bluetooth scan failed")
|
|
45
|
+
raise HTTPException(status_code=500, detail=str(exc))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@router.post("/phone/pair")
|
|
49
|
+
async def pair_device(request: Request, address: str):
|
|
50
|
+
"""Pair with a Bluetooth device by its MAC address."""
|
|
51
|
+
bt = request.app.state.bt_manager
|
|
52
|
+
try:
|
|
53
|
+
result = await bt.pair_device(address)
|
|
54
|
+
return {"status": "paired", "address": address, "detail": result}
|
|
55
|
+
except Exception as exc:
|
|
56
|
+
logger.exception("Bluetooth pairing failed for %s", address)
|
|
57
|
+
raise HTTPException(status_code=500, detail=str(exc))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@router.post("/phone/connect")
|
|
61
|
+
async def connect_device(request: Request, address: str):
|
|
62
|
+
"""Connect to an already-paired Bluetooth device."""
|
|
63
|
+
bt = request.app.state.bt_manager
|
|
64
|
+
try:
|
|
65
|
+
result = await bt.connect(address)
|
|
66
|
+
return {"status": "connected", "address": address, "detail": result}
|
|
67
|
+
except Exception as exc:
|
|
68
|
+
logger.exception("Bluetooth connect failed for %s", address)
|
|
69
|
+
raise HTTPException(status_code=500, detail=str(exc))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@router.post("/phone/disconnect")
|
|
73
|
+
async def disconnect_device(request: Request):
|
|
74
|
+
"""Disconnect the current Bluetooth device."""
|
|
75
|
+
bt = request.app.state.bt_manager
|
|
76
|
+
try:
|
|
77
|
+
result = await bt.disconnect()
|
|
78
|
+
return {"status": "disconnected", "detail": result}
|
|
79
|
+
except Exception as exc:
|
|
80
|
+
logger.exception("Bluetooth disconnect failed")
|
|
81
|
+
raise HTTPException(status_code=500, detail=str(exc))
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Routes for SMS send / receive management."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException, Query, Request
|
|
8
|
+
|
|
9
|
+
from routes.schemas import PaginatedResponse, SMSRecord, SMSRequest
|
|
10
|
+
from vendor.storage import store
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
router = APIRouter(tags=["sms"])
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@router.post("/sms", response_model=SMSRecord)
|
|
18
|
+
async def send_sms(request_body: SMSRequest, request: Request):
|
|
19
|
+
"""Send an SMS message via the connected phone."""
|
|
20
|
+
bt = request.app.state.bt_manager
|
|
21
|
+
try:
|
|
22
|
+
await bt.send_sms(request_body.phone_number, request_body.content)
|
|
23
|
+
except Exception as exc:
|
|
24
|
+
logger.exception("Failed to send SMS to %s", request_body.phone_number)
|
|
25
|
+
raise HTTPException(status_code=500, detail=f"Failed to send SMS: {exc}")
|
|
26
|
+
|
|
27
|
+
record = await store.save_sms({
|
|
28
|
+
"phone_number": request_body.phone_number,
|
|
29
|
+
"content": request_body.content,
|
|
30
|
+
"direction": "outgoing",
|
|
31
|
+
"status": "sent",
|
|
32
|
+
})
|
|
33
|
+
return SMSRecord(**record)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@router.get("/sms", response_model=PaginatedResponse)
|
|
37
|
+
async def list_sms(
|
|
38
|
+
page: int = Query(1, ge=1),
|
|
39
|
+
page_size: int = Query(20, ge=1, le=100),
|
|
40
|
+
phone_number: str | None = Query(None),
|
|
41
|
+
):
|
|
42
|
+
"""List SMS messages with optional phone-number filter and pagination."""
|
|
43
|
+
items, total = await store.list_sms(
|
|
44
|
+
page=page,
|
|
45
|
+
page_size=page_size,
|
|
46
|
+
phone_number=phone_number,
|
|
47
|
+
)
|
|
48
|
+
return PaginatedResponse(items=items, total=total, page=page, page_size=page_size)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Routes for aggregate statistics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter
|
|
6
|
+
|
|
7
|
+
from routes.schemas import StatsResponse
|
|
8
|
+
from vendor.storage import store
|
|
9
|
+
|
|
10
|
+
router = APIRouter(tags=["stats"])
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@router.get("/stats", response_model=StatsResponse)
|
|
14
|
+
async def get_stats():
|
|
15
|
+
"""Return aggregate statistics across calls, SMS, and contacts."""
|
|
16
|
+
data = await store.get_stats()
|
|
17
|
+
return StatsResponse(**data)
|