Add selectable CASAN IDE integrations
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""VS Code/GitHub Copilot adapter for the CASAN-owned `@casan` participant.
|
||||
|
||||
The VS Code extension owns the request and native model call, while this thin
|
||||
adapter maps participant lifecycle messages to the shared Plan-20 bridge. It
|
||||
does not call a model and it does not claim to intercept built-in Copilot chat.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
_ADAPTER_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
_BRIDGE_DIR = os.path.abspath(os.path.join(_ADAPTER_DIR, "..", "..", "scripts", "python"))
|
||||
if _BRIDGE_DIR not in sys.path:
|
||||
sys.path.insert(0, _BRIDGE_DIR)
|
||||
|
||||
import agentic_bridge as bridge # noqa: E402
|
||||
|
||||
ADAPTER_VERSION = "20.2.0-vscode"
|
||||
|
||||
|
||||
def emit(value, exit_code=0):
|
||||
sys.stdout.write(json.dumps(value, ensure_ascii=False) + "\n")
|
||||
return exit_code
|
||||
|
||||
|
||||
def handle_begin(payload):
|
||||
response = bridge.op_begin({
|
||||
"op": "begin",
|
||||
"client": "vscode",
|
||||
"client_version": payload.get("client_version"),
|
||||
"adapter_version": ADAPTER_VERSION,
|
||||
"project": payload.get("project") or payload.get("cwd"),
|
||||
"session": payload.get("session_id"),
|
||||
"turn": payload.get("turn_id"),
|
||||
"prompt": payload.get("prompt", ""),
|
||||
# The explicit @casan participant owns the complete model lifecycle.
|
||||
"integration_mode": "casan_owned",
|
||||
})
|
||||
return emit(response, 2 if response.get("decision") == "block" else 0)
|
||||
|
||||
|
||||
def handle_finalize(payload):
|
||||
response = bridge.op_finalize({
|
||||
"op": "finalize",
|
||||
"admission_id": payload.get("admission_id", ""),
|
||||
"stop_reason": payload.get("stop_reason") or "completed",
|
||||
"assistant_summary": payload.get("assistant_summary"),
|
||||
})
|
||||
return emit(response)
|
||||
|
||||
|
||||
def handle_abort(payload):
|
||||
response = bridge.op_abort({
|
||||
"op": "abort",
|
||||
"admission_id": payload.get("admission_id", ""),
|
||||
"reason": payload.get("reason") or "vscode_participant_aborted",
|
||||
})
|
||||
return emit(response)
|
||||
|
||||
|
||||
def handle_telemetry(payload):
|
||||
response = bridge.op_telemetry({
|
||||
"op": "telemetry",
|
||||
"admission_id": payload.get("admission_id", ""),
|
||||
"model": payload.get("model"),
|
||||
"runtime_ms": payload.get("runtime_ms"),
|
||||
"input_tokens": payload.get("input_tokens"),
|
||||
"output_tokens": payload.get("output_tokens"),
|
||||
"cost_amount": payload.get("cost_amount"),
|
||||
"cost_currency": payload.get("cost_currency"),
|
||||
"cost_source": payload.get("cost_source"),
|
||||
})
|
||||
return emit(response)
|
||||
|
||||
|
||||
HANDLERS = {
|
||||
"Begin": handle_begin,
|
||||
"Finalize": handle_finalize,
|
||||
"Abort": handle_abort,
|
||||
"Telemetry": handle_telemetry,
|
||||
}
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description="CASAN VS Code participant adapter")
|
||||
parser.add_argument("--event", required=True, choices=sorted(HANDLERS))
|
||||
args = parser.parse_args(argv)
|
||||
try:
|
||||
payload = json.loads(sys.stdin.read() or "{}")
|
||||
except ValueError:
|
||||
return emit({"decision": "block", "reason": "invalid_json"}, 2)
|
||||
try:
|
||||
return HANDLERS[args.event](payload)
|
||||
except Exception as exc: # noqa: BLE001 - adapter boundary
|
||||
return emit({"decision": "block", "reason": "adapter_error:%s" % exc}, 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user