콘텐츠로 이동

플랫폼이 부르는 도구

spec 은 도구 하나하나의 계약을 정하지 않는다 — 카탈로그는 에이전트가 describe_tools 로 알려 주는 대로 받는다. 예외가 플랫폼이 스스로 부르는 도구다. 아래 도구는 relay-service·command-service 가 이름을 알고 부르며, 출력의 필드를 읽는다. 이 표가 그 도구들의 계약이다. 에이전트는 여기 적힌 입력을 받아들이고, 적힌 출력 필드를 그 이름 그대로 준다.

에이전트는 필드를 더 줄 수 있고, 플랫폼은 모르는 필드를 무시한다. 표에 없는 kind 는 그 도구를 구현하지 않아도 된다.

도구 kind 누가 부르나 입력 출력에서 읽는 필드
describe_tools 전부 relay (핸드셰이크) {} tools[] — name, description, input_schema, requires_confirmation
workspace_info 전부 relay (핸드셰이크) {} 객체 전체 (64 KiB 까지 저장, 넘으면 {truncated: true})
screenshot chrome, android command-service (GET /resources/{id}/screen) {deliver_image: true} mime_type + image_base64 또는 image_blob(v1.1). 있으면 width·height
app_list android command-service (GET /resources/{id}/device-apps) {} apps[] — package, label, icon_png_base64(선택)
app_launch android app-service (POST /shortcuts/{id}/launch) {package} 상태만 본다 (ok 면 열렸다)
app_stop android 사용자 명령 (기기 앱 창 닫기) {package} 상태만 본다
  • 화면 동기화(prototype-web 의 App 창·기기 앱 창)는 이 도구를 주기적으로 부르는 것이다. command-service 는 리소스당 초당 2장을 넘겨 부르지 않고, max_age_ms 안의 화면은 다시 찍지 않는다.
  • deliver_image: true 를 주지 않으면 chrome·android 는 image_id 만 준다 — 플랫폼은 늘 true 를 준다.
  • 이미지가 relay_config.max_inline_bytes(256 KiB)보다 크면 v1.1 에이전트는 블롭으로 올리고 image_blob 을 준다. v1 에이전트는 base64 로 싣되, 프레임 상한(8 MiB)을 넘지 않게 줄여야 한다 (android 는 원본 PNG 를 8 MiB 까지 허용해 base64 로 바꾸면 상한을 넘을 수 있다 — 에이전트 감사의 항목).
  • mime_type 은 image/png·image/jpeg·image/webp 중 하나.
  • 실행할 수 있는 앱만 준다 (런처 activity 가 있는 것). 정책(--packages)에 막힌 앱은 빼고 준다 — 오류로 만들지 않는다.
  • icon_png_base64 는 선택이다. 주면 48~96px 정사각형 PNG, 앱 하나에 8 KiB 까지. 플랫폼은 data:image/png;base64,… 로 바꿔 DeviceApp.icon_data_url 에 싣는다. 넘으면 버린다 (null).
  • 앱이 많으면(수백 개) 출력이 커진다. 아이콘을 빼고 줘도 된다 — 화면이 기본 아이콘을 그린다.
  • 이미 떠 있으면 앞으로 가져온다 (오류가 아니다).
  • 실행할 수 없는 패키지면 status: "error", error_code: "app_not_launchable". 정책에 막혔으면 error_code: "capability_denied".

os_capabilities({})는 현재 지원 기능·설치 정책·한도를 반환한다. os_execute({type,input})는 공통 OS 계약의 동작을 실행하고 {interface_version,type,result,extensions?}를 반환한다. schema는 rest/os-interface.tsp에서 생성한 os-interface.json이 기준이다. 기존 도구와 연결 프레임은 유지한다.

Storage 경로 도구 workspace_storage_path (ENDUE-1162)

섹션 제목: “Storage 경로 도구 workspace_storage_path (ENDUE-1162)”

연결된 Storage 의 파일·폴더를 경로 단위로 넣고 빼고, 다른 Storage 를 가리키는 링크를 기기에 펼친다. 에이전트는 ready.capabilities 에 workspace_storage_path_v1 을 알린다. 이 능력이 없는 에이전트가 연결한 Storage 는 분리 상태에서만 이동·복사의 대상·원본이 되고, 링크를 걸거나 링크로 쓰는 일은 STORAGE_CAPABILITY_REQUIRED 로 거절된다.

플랫폼(workspace-service)만 이 도구를 부른다. 경로는 모두 Storage 루트 기준 상대 경로이고 에이전트가 아는 그 Storage 의 루트 안에서만 푼다. 권한(token)은 그 작업·링크·Storage·generation 에 묶인 단기 bearer 다.

모드 입력 하는 일 출력에서 읽는 필드
save_path storage_id, path, token, seal?, seal_until? 그 경로만 스캔·업로드하고 경로 단위로 커밋한다. seal 이면 그 경로를 기기에서 읽기 전용으로 두고 seal_until 까지 기억한다 revision, sealed
unseal_path storage_id, path 봉인을 푼다. 명령이 닿지 않아도 seal_until 이 지나면 스스로 푼다 상태만 본다
place_path storage_id, path, token, revision 그 revision 에 스테이징된 경로 아래를 받아 임시 폴더에서 해시를 확인하고 이름을 바꿔 공개한 뒤 경로 단위로 커밋한다. 경로가 이미 있으면 error_code: "storage_path_exists" revision
remove_path storage_id, path, token, expected_hash 저장한 뒤 바뀌지 않았는지 확인하고 기기에서 지운 뒤 제거를 커밋한다. 바뀌었으면 error_code: "storage_state_conflict" revision
link_pull link_id, path, token, revision 링크 대상 경로 아래를 받아 링크 경로에 공개한다. 이미 있으면 차이만. 기기에서 아직 저장하지 않은 링크 변경이 있는 파일은 덮지 않는다 revision
link_push link_id, token 링크 경로 아래의 바뀐 경로만 대상 Storage 로 커밋한다. 저장할 때마다 함께 부른다 revision, overwritten[]
link_remove link_id, path 링크 내용을 지운다. 저장하지 않은 변경은 복구 폴더(.endue-storage-recovery-*)로 옮긴다. 끊긴 링크면 빈 읽기 전용 폴더로 둔다 recovered[]
path_sync storage_id, token, revision, paths[] 원격에서 바뀐 경로를 받아 기기에 합친다. 기기에서 저장하지 않은 같은 파일은 덮지 않는다(다음 저장 때 나중 저장이 이긴다) revision
  • 같은 파일을 여러 writer 가 저장하면 나중 저장이 이긴다. 덮인 내용은 이전 revision 에 남는다. link_push 의 overwritten[] 은 그렇게 덮어쓴 경로다.
  • 저장(push)은 링크 경로를 스캔에서 빼고, 기준 revision 뒤의 원격 변경을 먼저 합친 뒤 바뀐 경로만 커밋한다.
  • 링크 루트 폴더를 기기에서 지우면 대상을 지우지 않고 다시 만든다. 링크 안의 파일을 지우면 대상에서도 지운다.