플러그인 개발자 문서
AnBoWork 데스크톱 앱용 플러그인 구축: AI용 새 도구 추가, 세션 옆에 자체 패널 고정, 시스템 알림 보내기, 새 파일 형식 구문 분석 등이 가능합니다. 하나의 Manifest.json과 하나의 입력 스크립트만 있으면 시작하기에 충분합니다.
01개요
AnBoWork 플러그인은 일반 Node.js 프로그램입니다. 설치 후 앱은 이를 독립형 하위 프로세스(Electron API가 아닌 순수 노드)로 분기하고 프로세스 간 메시지를 통해 통신합니다. SDK 패키지가 필요하지 않습니다. 필요한 것은 process.on('message') 및 process.send()뿐입니다.
플러그인이 수행할 수 있는 모든 작업은 manifest.json에 정적으로 선언되어 있습니다. 사전 설치 동의 페이지와 마켓플레이스 검토를 통해 플러그인 코드를 실행하지 않고도 추가되는 도구와 필요한 권한을 알 수 있습니다. 모든 UI(도구 모음 아이콘, 설정, 명령 팔레트, 상황에 맞는 메뉴)는 선언에서 호스트에 의해 렌더링됩니다. 플러그인 코드는 기본 창 내에서 실행되지 않습니다. 도킹된 보기와 부동 패널만 고유한 HTML이며 격리된 샌드박스 페이지에서 실행됩니다.
기능 개요
| 매니페스트 필드 | 능력 | 사용자가 볼 수 있는 위치 |
|---|---|---|
tools | AI용 호출 가능 도구 추가 | AI는 대화 중에 자동으로 호출합니다. 도구 호출이 세션에 표시됩니다. |
views | 세션의 오른쪽 사이드바에 고정된 영구 보기 | 세션 도구 모음의 추가 아이콘은 오른쪽에 페이지를 엽니다. |
ui | 독립형 부동 창 | 플러그인 목록의 "⋯" 메뉴에서 열림 |
sessionAction | 세션 도구 모음의 영구 작업 아이콘 | 한 번의 클릭으로 지정한 도구가 실행됩니다. |
configuration | 설정 페이지의 항목 | 설정 → 플러그인 구성; 호출할 때마다 값이 전달됩니다. |
commands | Ctrl/Cmd+K 명령 팔레트 항목 | 명령 팔레트 |
keybindings | 전역 키보드 단축키 | 키 조합으로 명령이 실행됩니다. |
menus | 세션 상황에 맞는 메뉴 항목 | 세션 행의 "⋯" / 마우스 오른쪽 버튼 클릭 메뉴 |
documentParsers | 입력 상자에 놓인 파일 구문 분석 | 사용자가 일치하는 파일을 삭제하면 자동으로 호출됩니다. |
activationEvents | 앱으로 함께 시작해보세요 | 보이지 않는; 백그라운드 타이머가 필요한 플러그인의 경우 |
permissions | 필수 권한 선언 | 사전 설치 동의 페이지 |
02빠른 시작
최소 플러그인에는 두 개의 파일만 필요합니다.
1. 매니페스트.json 작성
2. 참가 스크립트 작성
3. 앱에 설치
AnBoWork → 상단 표시줄 "도구" → "플러그인" → 오른쪽 상단의 "로컬 설치"를 연 다음 플러그인 폴더(또는 해당 zip)를 선택하세요. 동의 페이지에는 설치 전 선언된 권한과 모든 도구가 나열되어 있습니다. 활성화하려면 확인하세요.
4. 시도해 보세요
어떤 세션에서든 AI에게 "플러그인에게 Alice에게 인사하라고 요청하세요"라고 말합니다. 도구 설명에 따라 AI는 say_hello를 호출하기로 결정하고 호출과 그 결과가 세션에 나타납니다.
03매니페스트 필드
| 필드 | 유형 | 필수의 | 설명 |
|---|---|---|---|
id | string | 예 | 역방향 도메인 스타일(예: com.example.my-plugin. 문자, 숫자, 점, 하이픈만 사용할 수 있습니다. 일단 생성되면 변경할 수 없습니다. 동일한 ID를 다시 설치하는 것은 재설치로 간주됩니다. |
name | string | 예 | 플러그인 이름. description와 함께 모델에 컨텍스트로 제공되므로 영어가 권장됩니다. |
version | string | 예 | 의미론적 버전; 마켓플레이스는 이를 사용하여 업데이트를 감지합니다. |
description | string | 예 | 플러그인의 기능을 설명하는 한 문장(영어). |
author | string | 아니요 | 작가. |
readme | string | 아니요 | Marketplace 세부 정보 페이지에 표시되는 긴 형식 설명은 Markdown을 지원합니다. 그 안에 있는 이미지는 https URL이어야 합니다. zip에 번들로 포함된 파일의 상대 경로는 지원되지 않습니다. |
icon | string | 아니요 | 마켓플레이스 목록 및 세부정보 페이지에 표시되는 아이콘 - zip에 포함된 파일의 상대 경로(예: icon.png)입니다. SVG가 아닌 PNG여야 하며 최소 128×128이어야 합니다. |
main | string | 예 | 플러그인 폴더에 상대적인 항목 스크립트입니다. .. 폴더 이스케이프는 허용되지 않습니다. |
permissions | string[] | 예 | network / filesystem / notifications; 빈 배열일 수 있습니다. "권한 모델"을 참조하세요. |
tools | object[] | 예 | 도구 선언 빈 배열일 수 있습니다. "도구 및 통화 프로토콜"을 참조하세요. |
documentParsers | object[] | 아니요 | 파일 구문 분석 기능. |
ui | object | 아니요 | 플로팅 패널:{ entry, title } |
views | object[] | 아니요 | 고정된 뷰:{ id, title, icon, entry, width? } |
sessionAction | object | 아니요 | 툴바 아이콘은 플러그인당 최대 1개입니다. |
configuration | object[] | 아니요 | 설정 항목 목록입니다. |
commands | object[] | 아니요 | 명령 팔레트 항목. |
keybindings | object[] | 아니요 | 바로가기. command는 commands[] 항목의 tool를 참조해야 하며, 그렇지 않으면 설치가 거부됩니다. |
menus | object | 아니요 | 현재는 session/context 위치만 사용할 수 있습니다. |
activationEvents | string[] | 아니요 | 현재는 onStartupFinished만 가능합니다. |
텍스트의 언어 규칙
매니페스트의 텍스트에는 두 가지 대상이 있습니다. 모델의 경우: name, description, tools[].description, tools[].parameters.*.description. 영어로 작성하세요. 모델은 영어 도구 설명을 이해하고 매개변수를 보다 안정적으로 입력합니다. 사람의 경우: tools[].summary(동의 페이지의 한 줄 요약), ui.title, views[].title, sessionAction.tooltip, configuration[].label, commands[].title 및 title는 menus 내부에 있습니다. 대상 사용자의 언어로 작성하세요.
04권한 모델
permissions 코드가 실제로 수행하는 작업을 솔직하게 반영해야 합니다. 사전 설치 동의 페이지에는 사용자가 설치 여부를 결정할 수 있도록 각 항목이 나열되어 있습니다. 마켓플레이스 검토에서는 코드에 대한 선언도 확인합니다.
| 허가 | 선언해야 하는 경우 | 호스트가 어떻게 대하는지 |
|---|---|---|
filesystem | 사용자 파일 읽기 또는 쓰기(프로젝트 코드 읽기, 문서 생성, 홈 폴더에 데이터 저장) | 사전 동의가 사용자에게 표시됩니다. |
network | 네트워크 요청(타사 API, 다운로드) | 사전 동의가 사용자에게 표시됩니다. |
notifications | show_notification 역방향 RPC를 통해 시스템 알림 표시 | Enforced: 선언 없이 호출하면 host_error가 반환되고 알림이 표시되지 않습니다. |
filesystem 및 network는 현재 런타임 샌드박스가 아닌 동의 수준 선언입니다. 호스트는 fs 또는 fetch를 가로채지 않습니다. 이것이 바로 선언이 정직해야 하는 이유입니다. 과소 선언된 플러그인은 마켓플레이스 검토에서 거부되며 발견되면 사용자 신뢰를 잃습니다. 둘 중 하나를 과도하게 선언하지 마십시오(사용하지 않는 권한은 사용자를 주저하게 만듭니다).개인정보 보호 및 데이터
context.cwd은 사용자의 프로젝트 폴더이며 소스 코드와 민감한 구성이 포함될 수 있습니다. 도구 인수에는 사용자의 대화가 포함될 수 있습니다. 기능에서 요구하지 않는 한 네트워크를 통해 이 데이터를 전송하지 마십시오. 전송하는 경우 description 및 summary에 무엇이 전송되고 누구에게 전송되는지 명시하십시오. 플러그인 ID의 이름을 딴 사용자 홈 폴더 아래 파일에 플러그인 자체의 영구 데이터를 보관하면 제거 시 쉽게 찾을 수 있습니다.
05도구 및 통화 프로토콜
선언
| 필드 | 설명 |
|---|---|
name | 전체 앱에서 고유한 소문자 및 밑줄로 된 도구 이름(내장 도구 및 기타 플러그인 도구와 함께 모델에 등록됨) |
description | 모델에 대한 설명(영어)입니다. 세 가지를 기술하십시오. 도구가 수행하는 작업, 도구를 호출해야 할 때 사용자가 말하는 내용, 호출해서는 안 되는 경우입니다. 이는 AI가 플러그인을 사용하는지 여부에 대한 가장 중요한 단일 필드입니다. |
summary | 사람이 읽을 수 있는 한 줄 요약이 동의 페이지에 표시됩니다. 선택사항이지만 적극 권장됩니다. 그렇지 않으면 잘린 설명이 대신 표시됩니다. |
parameters | 모든 속성에 description가 있는 표준 JSON 스키마 개체입니다. 모델은 인수를 채우고 호스트는 추가 검증 없이 이를 전달하므로 코드에서 필수 필드를 확인하세요. |
renderAs | 선택 과목; 현재 checklist만: 호스트는 호출 인수의 todos 배열을 체크리스트 카드로 렌더링합니다. 아래를 참조하세요. |
tools[]에 선언된 도구 이름만 호출할 수 있습니다. — sessionAction.tool, commands[].tool 및 menus 내부의 tool 필드는 설치 시 비어 있지 않은 문자열인지 확인만 됩니다. 호스트는 않고 이름이 tools[]에 선언되었는지 확인하지 않고 버튼, 바로가기 또는 메뉴 항목이 실행될 때 여전히 해당 이름으로 호출을 전달합니다. 따라서 순전히 UI로 실행되는 작업은 tools[]에 표시되지 않고 index.js에서 완전히 처리될 수 있지만 AI는 이를 보거나 호출할 수 없습니다. 클릭과 AI의 채팅 요청에 의해 동일한 작업이 실행되도록 하려면 tools[]에도 동일한 이름을 선언하여 두 진입점이 하나의 핸들러를 공유하도록 합니다. UI 전용으로 유지하려는 경우 선언하지 않은 상태로 두십시오. 완성된 것처럼 보이도록 항목을 추가할 필요가 없습니다.메시지 프로토콜
호스트는 call_tool;을 보냅니다. 플러그인은 동일한 requestId을 포함하는 tool_result 또는 tool_error로 응답해야 합니다. 30초 이내에 응답이 없는 호출은 시간이 초과되고 모델에 오류가 발생합니다.
content는 text 및 image 블록만 허용합니다(base64 data + mimeType 이미지). 다른 유형은 삭제됩니다. details는 모델에 전혀 제공되지 않는 임의의 구조화된 데이터입니다. 이는 호스트 UI 렌더링 및 사용자 고유의 도킹된 보기를 위한 것입니다.
파일 결과: 파일 카드
체크리스트 렌더링: renderAs 체크리스트
좋은 설명 작성하기
명령형("사용자가 요청하면 이것을 호출하세요...") 및 상태 제외("...를 위해 호출하지 마세요")의 트리거를 설명합니다. 결과가 파일인 경우 생성된 파일 링크를 주장하는 대신 반환된 파일 링크를 참조하도록 모델에 요청하세요. 인수가 외부 생성 API로 전달되는 경우 어떤 언어로 작성해야 하는지 알려주세요. "할 일 관리"와 같은 한 줄짜리 명령은 피하세요. 모델은 언제 도구를 사용해야 할지 알 수 없습니다.
06고정된 뷰(뷰)
고정된 보기는 세션의 오른쪽 사이드바에 있는 영구 페이지입니다. 추가 아이콘이 세션 도구 모음에 나타나고 HTML이 열릴 때 오른쪽에 표시됩니다. 페이지 상태(스크롤 위치, 초안)는 VS Code 사이드바 보기와 동일한 의미로 세션 전환 및 축소/확장 후에도 유지됩니다.
| 필드 | 설명 |
|---|---|
id | 플러그인 내에서 고유합니다. |
title | 아이콘에 대한 도구 설명 텍스트(사람이 읽을 수 있음) |
icon | 호스트 허용 목록에서 선택하세요: git-branch, checklist. 앱 전체에서 아이콘을 일관되게 유지합니다. 사용자 정의 이미지는 허용되지 않습니다. |
entry | 플러그인 폴더에 상대적인 HTML 파일입니다. |
width | 선택적 기본 패널 너비(픽셀), 240~640, 기본 360. 사용자는 드래그하여 크기를 조정할 수 있으며 크기는 기억됩니다. |
페이지 런타임
페이지는 샌드박스(sandbox + contextIsolation, 노드 없음, 호스트 앱 데이터에 대한 액세스 없음)에서 실행되며 window.pluginHost의 몇 가지 방법을 통해서만 자체 플러그인 프로세스와 통신할 수 있습니다. 자신만의 스타일을 가져오세요. 아래 예와 같이 앱의 밝은/어두운 구성표를 따르는 것이 좋습니다.
권장 패턴: 처음 로드할 때 invoke()를 사용하여 자체 쿼리 도구 중 하나를 호출하고 details에 구조화된 데이터를 반환하도록 합니다. 그런 다음 폴링 대신 ui_push를 사용하여 플러그인 프로세스의 모든 변경 사항을 푸시합니다. AI가 대화의 데이터를 변경하면 패널이 즉시 새로 고쳐집니다.
07부동 패널(ui)
ui: { entry, title } 사용자가 플러그인 목록의 "⋯" 메뉴에서 여는 독립형 부동 창(900×700)을 선언합니다. 닫히면 파괴됩니다. 페이지 환경과 window.pluginHost API는 도킹 뷰와 동일하며, ui_push는 플로팅 패널과 도킹 뷰 모두에 전달됩니다. 가끔씩 열리는 대형 패널에 적합합니다. 세션 옆에 있어야 하는 콘텐츠에는 views를 사용하세요.
08세션 도구 모음 아이콘(sessionAction)
플러그인당 최대 하나의 영구 아이콘입니다. 이를 클릭하면 빈 인수로 tool가 호출되므로 해당 도구는 매개변수 없이 의미 있는 작업을 수행해야 합니다.
| 필드 | 설명 |
|---|---|
tool | 클릭 시 호출하는 도구입니다. |
icon | 허용 목록에 있는 아이콘 이름입니다. |
tooltip | 텍스트를 가리킵니다. |
visibleTool | 선택 과목. 설정되면 렌더링하기 전에 빈 인수로 호출되며 결과의 부울 details.visible에 따라 아이콘 표시 여부가 결정됩니다. "현재 폴더가 git 저장소인지"와 같은 런타임 검사에 유용합니다. |
09설정(구성)
선언된 항목은 설정 페이지의 플러그인 구성 아래에 표시됩니다. 호스트는 사용자가 변경한 값을 저장하고 호출이 AI, 도구 모음 아이콘 또는 패널에서 오는지 여부에 관계없이 모든 call_tool(id로 입력, defaultValue로 대체)마다 context.config로 전달합니다. 당신은 그들을 요구할 필요가 없습니다.
| type | 다음으로 렌더링됨 | defaultValue 유형 |
|---|---|---|
select | 단일 선택 목록; 옵션은 optionsTool에서 옵니다. | string |
boolean | 토글 스위치 | boolean |
string | 흐림에 적용되는 텍스트 입력 | string |
number | 숫자입력 | number |
10명령 팔레트/바로가기/컨텍스트 메뉴
세 가지 모두 "빈 인수로 도구 호출"에 대한 서로 다른 진입점입니다. 플러그인은 여러 개를 선언할 수 있습니다.
| 필드 | 모양 | 설명 |
|---|---|---|
commands | { tool, icon, title }[] | Ctrl/Cmd+K 명령 팔레트에 표시되며 사용자가 검색한 후 트리거됩니다. |
keybindings | { command, key }[] | command는 commands[] 항목의 tool와 동일해야 합니다. key는 mod+shift+g 표기법을 사용합니다. 여기서 mod는 macOS의 Cmd이고 다른 곳에서는 Ctrl입니다. 다른 단축키와의 충돌은 정적으로 확인되지 않으므로 일반적이지 않은 조합을 선택하세요. |
menus | { "session/context": { tool, icon, title }[] } | 세션 행의 메뉴에 추가되었습니다. 현재는 이 위치만 사용할 수 있습니다. |
11문서 파서(documentParsers)
사용자가 입력 상자에 파일을 놓으면 호스트는 활성화된 플러그인에 의해 선언된 파서를 MIME 유형별로 조회하고 파일 콘텐츠를 일치하는 toolName에 base64로 전달합니다. 이는 AI가 호출하기로 결정한 도구가 아니므로 하지 마세요 tools 아래에 파서 도구를 나열하지 마세요. 그렇지 않으면 AI 호출 가능 도구로 노출됩니다.
12역방향 RPC(host_request)
플러그인 프로세스에는 Electron API가 없습니다. 실제 시스템 기능이 필요할 때 호스트에 host_request를 보내고 호스트는 host_response 또는 host_error로 응답합니다. 이 채널은 call_tool와 완전히 독립적입니다. 도구 호출을 처리하는 동안이나 타이머에서 사용할 수 있습니다.
| capability | params | result | 전제조건 |
|---|---|---|---|
show_notification | { title, body?, viewId? } | { shown: true } / { shown: false, reason: "disabled" | "unsupported" } | notifications 권한이 필요합니다. 사용자가 설정에서 데스크톱 알림을 끄면 오류 대신 비활성화된 값이 반환됩니다. viewId가 고정된 뷰 중 하나를 가리키면 알림을 클릭하면 앱이 맨 앞으로 이동하고 해당 뷰가 확장됩니다. |
render_pdf | { outputPath, title, content } | {} | 콘텐츠는 마크다운입니다. 호스트는 내장 렌더러를 사용하여 PDF를 outputPath로 렌더링합니다. |
13수명주기
| 단계 | 행동 |
|---|---|
| 시작 | 기본적으로 지연: 앱으로 시작되지 않고 도구(AI, 도구 모음 아이콘, 패널, 명령, 문서 구문 분석) 중 하나에 대한 첫 번째 호출에서 분기됩니다. activationEvents: ["onStartupFinished"]를 선언하는 플러그인은 앱 실행이 완료된 직후에 시작됩니다. 일반 도구 플러그인이 아닌 백그라운드 타이머(알림, 폴링)가 필요한 플러그인에만 이 기능을 사용하세요. |
| 거주자 | 일단 시작된 프로세스는 활성 상태로 유지되며 도구 호출 전반에 걸쳐 재사용됩니다. 상태를 메모리에 캐시할 수 있지만 언제든지 다시 시작할 수 있다고 가정합니다. |
| 충돌 | 프로세스가 예기치 않게 종료되면 호스트는 프로세스를 즉시 다시 시작하고 5초 및 15초 후에 다시 시작합니다. 3번 연속 실패하면 "충돌"로 표시되고 더 이상 재시도되지 않습니다. 사용자는 플러그인 페이지에서 상태를 볼 수 있습니다. 기내 통화는 모두 오류를 반환합니다. |
| 비활성화 / 제거 / 재설치 | 프로세스가 종료되고 도킹된 뷰와 부동 패널이 삭제됩니다. 다시 설치하면 전체 폴더가 대체됩니다. |
| 로그 | stdout/stderr는 플러그인 ID 접두사가 붙은 앱 로그 파일에 기록됩니다. 일반 console.log는 디버깅에 충분합니다. "디버깅 및 FAQ"를 참조하세요. |
ELECTRON_RUN_AS_NODE=1로 시작하고, cwd은 플러그인 설치 폴더이며, 노드 버전은 앱에 번들로 제공되는 Electron과 일치합니다. 전체적으로 설치된 패키지에 의존하지 말고 npx가 존재한다고 가정하지 마십시오.14포장 및 출판
포장
아카이브 루트에 manifest.json로 플러그인 폴더를 압축합니다. 타사 종속성이 있는 경우 전체 node_modules를 배송하는 대신 먼저 esbuild/webpack을 사용하여 단일 파일로 묶습니다.
마켓플레이스에 게시
AnBoWork → 도구 → 플러그인 → '마켓플레이스' 탭 → 오른쪽 상단의 '플러그인 게시'를 누른 다음 zip을 업로드하세요. 제출물은 매니페스트 선언이 코드(특히 권한)와 일치하는지 확인하는 검토 단계로 들어갑니다. 승인되면 다른 사용자가 마켓플레이스에서 해당 플러그인을 찾아서 설치할 수 있으며, AI는 필요하다고 판단될 때 자동으로 사용자를 위해 검증된 플러그인을 설치할 수 있습니다.
업데이트
version를 범하고 다시 게시하세요. 앱은 설치된 버전을 마켓플레이스 버전과 비교하고 업데이트하라는 메시지를 표시합니다. 다시 설치하면 사용자의 활성화된 상태와 설정 값이 유지됩니다.
15전체 예: Todo Quadrant
실제 작동하는 플러그인(손질됨): AI는 할 일을 추가 및 제거할 수 있고, 오른쪽 사이드바에는 실시간으로 새로 고쳐지는 보드가 표시되며, 시스템 알림 알림을 보낼 수 있습니다. 이 세 가지를 연결하면 도구 프로토콜, 도킹 뷰 푸시 및 역방향 RPC가 포함됩니다.
16디버깅 및 FAQ
| 징후 | 원인 및 수정 |
|---|---|
| 설치 시 매니페스트 검증 실패 | 메시지에 표시된 대로 "매니페스트 필드" 표와 비교하여 각 필드를 확인하세요. id 형식, 기본/항목에는 ..가 포함되어서는 안 되며, 아이콘은 허용 목록에 있어야 하고, 키 바인딩 명령은 명령의 기존 도구를 가리켜야 하며, 너비는 240~640 사이입니다. |
| AI는 내 도구를 호출하지 않습니다. | 거의 항상 description 문제가 발생합니다. 트리거가 불분명하거나 영어로 작성되지 않았습니다. "좋은 설명 작성"을 참조하세요. 또한 도구 이름이 다른 도구와 충돌하지 않는지 확인하십시오. |
| 통화 시간 초과(30초) | 항목 스크립트가 tool_result로 응답하지 않았습니다. 일반적으로 requestId가 반향되지 않거나, type 메시지의 철자가 틀리거나, 스크립트가 시작 시 던져지고 종료되었습니다. 앱 로그에서 [plugin:your-id] 접두사가 붙은 줄을 찾아보세요. |
| 플러그인 상태가 "충돌됨"으로 표시됩니다. | 3연속 선발 실패. 일반적으로 누락된 패키지의 require; 플러그인 폴더에서 node index.js를 실행하면 재현됩니다. 수정 후 플러그인 페이지에서 플러그인을 껐다가 다시 켜세요. |
| 패널이 공백으로 열립니다. | entry 경로가 잘못되었거나 페이지에 JS 오류가 있습니다. 페이지는 노드의 require 없이 샌드박스에서 실행됩니다. window.pluginHost만 사용할 수 있습니다. |
| 알림이 표시되지 않습니다 | 순서대로 확인: 매니페스트가 notifications를 선언합니다. 결과는 shown:false(사용자가 데스크톱 알림을 껐음)이 아닙니다. OS는 AnBoWork의 알림을 허용합니다. |
| 설정 값을 읽을 수 없습니다. | 값은 params이 아닌 message.context.config[id]에 있습니다. |
로그 파일 위치
| 운영체제 | 길 |
|---|---|
| macOS | ~/Library/Logs/AnBoWork/main.log |
| Windows | %USERPROFILE%\AppData\Roaming\AnBoWork\logs\main.log |