clawops 0.2.2__tar.gz → 0.2.4__tar.gz
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.
- clawops-0.2.4/.github/workflows/publish.yml +55 -0
- {clawops-0.2.2 → clawops-0.2.4}/PKG-INFO +2 -2
- {clawops-0.2.2 → clawops-0.2.4}/README.md +1 -1
- {clawops-0.2.2 → clawops-0.2.4}/docs/agent.md +39 -0
- clawops-0.2.4/src/clawops/_version.py +1 -0
- clawops-0.2.2/.claude/settings.local.json +0 -22
- clawops-0.2.2/src/clawops/_version.py +0 -1
- {clawops-0.2.2 → clawops-0.2.4}/.gitignore +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/pyproject.toml +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_base_client.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_client.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_constants.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_exceptions.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_models.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_resource.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/_utils.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_agent.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_audio.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_control_ws.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_media_ws.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_recorder.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_session.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/_tool.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/mcp/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/mcp/_http.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/mcp/_stdio.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/pipeline/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/pipeline/_base.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/pipeline/_realtime_session.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/plugins/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/agent/plugins/openai_realtime.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/pagination.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/py.typed +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/resources/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/resources/accounts.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/resources/calls.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/resources/numbers.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/resources/sip/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/resources/sip/credentials.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/call.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/call_params.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/number.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/number_params.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/shared.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/sip/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/sip/credential.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/types/sip/credential_params.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/src/clawops/webhooks.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/__init__.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_agent.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_audio.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_control_ws.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_integration.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_mcp.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_media_ws.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_pipeline_base.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_realtime_session.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_recorder.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_session.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/agent/test_tool.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/conftest.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_agent_exceptions.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_base_client.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_calls.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_client.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_exceptions.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_integration.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_models.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_numbers.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_pagination.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_params.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_sip_credentials.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_types.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_utils.py +0 -0
- {clawops-0.2.2 → clawops-0.2.4}/tests/test_webhooks.py +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'src/clawops/_version.py'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: '3.12'
|
|
17
|
+
- run: pip install -e ".[dev]"
|
|
18
|
+
- run: pytest tests/ -v
|
|
19
|
+
|
|
20
|
+
publish:
|
|
21
|
+
needs: test
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
id-token: write
|
|
25
|
+
contents: write
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: '3.12'
|
|
31
|
+
|
|
32
|
+
- name: Extract version
|
|
33
|
+
id: version
|
|
34
|
+
run: |
|
|
35
|
+
VERSION=$(python -c "exec(open('src/clawops/_version.py').read()); print(__version__)")
|
|
36
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
37
|
+
|
|
38
|
+
- run: pip install build
|
|
39
|
+
- run: python -m build
|
|
40
|
+
|
|
41
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
42
|
+
|
|
43
|
+
- name: Create git tag
|
|
44
|
+
run: |
|
|
45
|
+
git tag "v${{ steps.version.outputs.version }}"
|
|
46
|
+
git push origin "v${{ steps.version.outputs.version }}"
|
|
47
|
+
|
|
48
|
+
- name: Create GitHub Release
|
|
49
|
+
env:
|
|
50
|
+
GH_TOKEN: ${{ github.token }}
|
|
51
|
+
VERSION: ${{ steps.version.outputs.version }}
|
|
52
|
+
run: |
|
|
53
|
+
gh release create "v${VERSION}" dist/* \
|
|
54
|
+
--title "v${VERSION}" \
|
|
55
|
+
--generate-notes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clawops
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: The official Python library for the ClawOps Voice API
|
|
5
5
|
Project-URL: Homepage, https://github.com/learners-superpumped/clawops-python
|
|
6
6
|
Project-URL: Documentation, https://docs.claw-ops.com
|
|
@@ -104,7 +104,7 @@ async def on_start(call):
|
|
|
104
104
|
agent.listen() # WebSocket 연결 후 인바운드 대기
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
> 자세한 사용법은 **[Agent 문서](docs/agent.md)** 를 참고하세요.
|
|
107
|
+
> 자세한 사용법은 **[Agent 문서](docs/agent.md)** 를 참고하세요. (Tool, 이벤트, 통화 녹음, 파이프라인 모드, MCP 연동 등)
|
|
108
108
|
|
|
109
109
|
## REST API 사용법
|
|
110
110
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
- [설정 옵션](#설정-옵션)
|
|
11
11
|
- [Tool (함수 호출)](#tool-함수-호출)
|
|
12
12
|
- [이벤트 핸들러](#이벤트-핸들러)
|
|
13
|
+
- [통화 녹음](#통화-녹음)
|
|
13
14
|
- [파이프라인 모드 (커스텀 STT/LLM/TTS)](#파이프라인-모드-커스텀-sttllmtts)
|
|
14
15
|
- [MCP 서버 연동](#mcp-서버-연동)
|
|
15
16
|
- [CallSession](#callsession)
|
|
@@ -100,6 +101,10 @@ agent = ClawOpsAgent(
|
|
|
100
101
|
eagerness="high", # 응답 적극성: low, medium, high, auto
|
|
101
102
|
greeting=True, # 첫 인사 자동 생성 여부
|
|
102
103
|
|
|
104
|
+
# 녹음
|
|
105
|
+
recording=True, # 통화 녹음 활성화
|
|
106
|
+
recording_path="./recordings", # 저장 경로 (기본값: ./recordings)
|
|
107
|
+
|
|
103
108
|
# 고급
|
|
104
109
|
base_url="https://api.claw-ops.com", # API 엔드포인트
|
|
105
110
|
)
|
|
@@ -198,6 +203,35 @@ async def on_transcript(call, role, text):
|
|
|
198
203
|
| `call_end` | `(call)` | 통화 종료 |
|
|
199
204
|
| `transcript` | `(call, role, text)` | 음성 텍스트 생성 |
|
|
200
205
|
|
|
206
|
+
## 통화 녹음
|
|
207
|
+
|
|
208
|
+
`recording=True`로 통화를 실시간 녹음할 수 있습니다. 통화마다 3개 WAV 파일(PCM16 8kHz mono)이 생성됩니다.
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
agent = ClawOpsAgent(
|
|
212
|
+
from_="07012341234",
|
|
213
|
+
system_prompt="상담원입니다.",
|
|
214
|
+
recording=True,
|
|
215
|
+
recording_path="./recordings", # 기본값
|
|
216
|
+
)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 생성되는 파일
|
|
220
|
+
|
|
221
|
+
| 파일 | 내용 |
|
|
222
|
+
|------|------|
|
|
223
|
+
| `{call_id}_in.wav` | 발신자 음성 (수신 오디오) |
|
|
224
|
+
| `{call_id}_out.wav` | AI 응답 (송신 오디오) |
|
|
225
|
+
| `{call_id}_mix.wav` | 양방향 믹스 |
|
|
226
|
+
|
|
227
|
+
### 동작 원리
|
|
228
|
+
|
|
229
|
+
- 수신 오디오(발신자)가 타임라인 역할을 합니다
|
|
230
|
+
- 송신 오디오(AI 응답)는 버퍼에 쌓이고, 수신 청크가 올 때마다 같은 길이만큼 꺼내서 샘플 단위로 믹스합니다
|
|
231
|
+
- 별도 시간 관리 없이 자연스럽게 정렬됩니다
|
|
232
|
+
- 파일은 실시간으로 기록되므로 통화 중 디스크에 바로 저장됩니다
|
|
233
|
+
- 통화 종료 시 WAV 헤더가 최종 크기로 업데이트됩니다
|
|
234
|
+
|
|
201
235
|
## 파이프라인 모드 (커스텀 STT/LLM/TTS)
|
|
202
236
|
|
|
203
237
|
OpenAI Realtime 대신 직접 STT, LLM, TTS 프로바이더를 조합할 수 있습니다.
|
|
@@ -374,6 +408,11 @@ ClawOpsAgent
|
|
|
374
408
|
│ ├── to_openai_tools() # JSON Schema 자동 생성
|
|
375
409
|
│ └── call() # 이름으로 함수 호출
|
|
376
410
|
│
|
|
411
|
+
├── AudioRecorder (콜별) # 실시간 녹음 (recording=True 시)
|
|
412
|
+
│ ├── write_inbound() # 수신 오디오 → _in.wav + _mix.wav
|
|
413
|
+
│ ├── write_outbound() # 송신 오디오 → _out.wav + mix 버퍼
|
|
414
|
+
│ └── stop() # WAV 헤더 업데이트
|
|
415
|
+
│
|
|
377
416
|
├── CallSession (콜별) # 통화 상태 관리
|
|
378
417
|
│ ├── audio_stream() # 수신 오디오 스트림
|
|
379
418
|
│ ├── send_audio() # 응답 오디오 전송
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.4"
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Read(//Users/ghyeok/Developments/clawops/**)",
|
|
5
|
-
"WebSearch",
|
|
6
|
-
"mcp__plugin_context7_context7__resolve-library-id",
|
|
7
|
-
"mcp__plugin_context7_context7__query-docs",
|
|
8
|
-
"Bash(git:*)",
|
|
9
|
-
"Bash(pip install:*)",
|
|
10
|
-
"Bash(pytest:*)",
|
|
11
|
-
"Bash(python:*)",
|
|
12
|
-
"Bash(mypy:*)",
|
|
13
|
-
"Bash(ruff check:*)",
|
|
14
|
-
"Bash(twine upload:*)",
|
|
15
|
-
"Bash(node:*)",
|
|
16
|
-
"Skill(commit-commands:commit)",
|
|
17
|
-
"Bash(git rm:*)",
|
|
18
|
-
"Bash(grep:*)",
|
|
19
|
-
"Bash(gcloud compute ssh sip-callbot-vm:*)"
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|