apick-api 3.9.0 → 3.11.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 +20 -4
- package/LICENSE +21 -21
- package/README.md +30 -12
- package/SECURITY.md +11 -11
- package/docs/guide.en.md +11 -6
- package/docs/guide.ko.md +11 -6
- package/docs/subagent.md +39 -0
- package/docs/tts.md +54 -0
- package/package.json +71 -71
- package/src/index.cjs +44 -13
- package/src/index.d.ts +76 -42
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 3.11.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
- TTS voice metadata includes documented preset age evidence; case aliases remain supported without duplicate catalog entries. Reservation reductions are included in `billing.released`.
|
|
4
|
+
- 목소리 목록에 공식 설정 연령 근거를 추가하고 대소문자 별칭 호환을 유지합니다. 예약 감액은 `billing.released`에 누적됩니다.
|
|
4
5
|
|
|
5
|
-
-
|
|
6
|
-
-
|
|
6
|
+
- TTS: Gemini direct synthesis, queue fallback, default-on paid normalization, unified MP3/ASS and billing.
|
|
7
|
+
- TTS: Gemini 직접 합성, 대기 상태별 전환, 기본 on 유료 정규화, 공통 MP3·ASS와 정산 내역.
|
|
8
|
+
- 이미지 생성·편집: 사용량 미확정 시 202와 작업 ID를 반환하는 정산 보류 응답 타입을 추가했습니다.
|
|
9
|
+
- Image generation/editing: added the HTTP 202 settlement-pending response type for unconfirmed usage.
|
|
10
|
+
|
|
11
|
+
# 3.10.0 — 2026-10-04
|
|
12
|
+
|
|
13
|
+
서브에이전트 전용 REST 메서드와 타입을 추가했습니다. 설치형 스킬의 사용량 과금 정보를 제공합니다.
|
|
14
|
+
|
|
15
|
+
Adds the Subagent integration and usage-based installed-agent contract. Existing API contracts remain supported.
|
|
16
|
+
|
|
17
|
+
# Changelog
|
|
18
|
+
|
|
19
|
+
## 3.9.0 — 2026-10-04
|
|
20
|
+
|
|
21
|
+
- `getSkillPerformance()`와 공개 성능표 타입을 추가했습니다. 시험 방식·표본 수·평가일·성공률 구간·미검증 상태를 확인할 수 있습니다.
|
|
22
|
+
- Add `getSkillPerformance()` and report types for methods, sample sizes, evaluation dates, success-rate intervals and untested states.
|
|
7
23
|
|
|
8
24
|
## 3.8.1 — 2026-10-03
|
|
9
25
|
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 APICK
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 APICK
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -101,8 +101,8 @@ Leave the allowed-IP list blank for unrestricted access. To restrict access, reg
|
|
|
101
101
|
| `requestHealthCheckup(input)` / `getHealthCheckup(transactionId)` | 국가 건강검진 결과 조회 / National health checkup results | JSON |
|
|
102
102
|
| `requestCashReceiptDeduction(input)` / `getCashReceiptDeduction(transactionId)` | 현금영수증 소득공제 내역 / Cash receipt income deductions | JSON |
|
|
103
103
|
| `requestTaxReturnHistory(input)` / `getTaxReturnHistory(transactionId)` | 국세 신고내역 조회 / National tax return history | JSON |
|
|
104
|
-
| `searchSkills(options)` / `getSkill(skillId)` | Skill 검색·상세 / Search and inspect Skills | JSON |
|
|
105
|
-
| `getSkillPerformance()` | 시험 방법·표본 수·기계 검사·품질 점수 / Measured results and methods | JSON |
|
|
104
|
+
| `searchSkills(options)` / `getSkill(skillId)` | Skill 검색·상세 / Search and inspect Skills | JSON |
|
|
105
|
+
| `getSkillPerformance()` | 시험 방법·표본 수·기계 검사·품질 점수 / Measured results and methods | JSON |
|
|
106
106
|
| `quoteSkill(skillId, input, options)` | Skill 견적(무료) / Quote a run (free) | JSON |
|
|
107
107
|
| `runSkill(skillId, input, options)` | Skill 실행 / Run a Skill | JSON |
|
|
108
108
|
| `getSkillRun(runId)` / `getSkillRunResult(runId)` / `cancelSkillRun(runId)` | 실행 조회·결과·취소 / Read, fetch result, cancel | JSON |
|
|
@@ -116,7 +116,7 @@ Search and run reviewed Skills. Points are charged only when a result in the pro
|
|
|
116
116
|
```js
|
|
117
117
|
import { randomUUID } from 'node:crypto';
|
|
118
118
|
|
|
119
|
-
const found = await apick.searchSkills({ query: '상품명', limit: 5 });
|
|
119
|
+
const found = await apick.searchSkills({ query: '상품명', limit: 5 });
|
|
120
120
|
const skillId = found.data.items[0].skill_id;
|
|
121
121
|
const detail = await apick.getSkill(skillId); // input_schema, output_schema, price_points, estimated_points
|
|
122
122
|
const input = { product_name: '튼튼한 접이식 우산' };
|
|
@@ -131,11 +131,11 @@ while (!['succeeded', 'failed', 'timed_out', 'cancelled'].includes(run.status))
|
|
|
131
131
|
console.log(run.status, run.billing, run.result);
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
검증 결과는 [스킬 성능표](https://apick.app/skills/performance) 또는 `const { data } = await apick.getSkillPerformance()`로 확인합니다. 표본 수·시험일·방법·기계 검사 통과율과 모델 평가 점수를 함께 읽으세요. 미검증 값은 `null`이며, 과거의 다른 조건에서 얻은 점수는 `legacy`로 구분합니다. 모델 점수는 객관적 정확도나 판매 성과 보장이 아닙니다.
|
|
135
|
-
|
|
136
|
-
See the [Skill performance report](https://apick.app/skills/performance) or call `const { data } = await apick.getSkillPerformance()`. Read sample sizes, dates, methods, machine checks and model scores together. Unmeasured values are `null`; historical results under different conditions are in `legacy`. Model scores are not objective accuracy or sales guarantees.
|
|
137
|
-
|
|
138
|
-
`searchSkills({ sort })` 로 추천(`recommended`)·인기(`popular`)·많이 사용(`used`)·좋아요순(`likes`)·평점순(`rating`)·최신(`new`) 순서를 고르고, 검색·상세 응답의 `usage_label`(사용 건수 구간)·`like_count`·`review_count`·`rating_average` 로 Skill 을 비교할 수 있습니다.
|
|
134
|
+
검증 결과는 [스킬 성능표](https://apick.app/skills/performance) 또는 `const { data } = await apick.getSkillPerformance()`로 확인합니다. 표본 수·시험일·방법·기계 검사 통과율과 모델 평가 점수를 함께 읽으세요. 미검증 값은 `null`이며, 과거의 다른 조건에서 얻은 점수는 `legacy`로 구분합니다. 모델 점수는 객관적 정확도나 판매 성과 보장이 아닙니다.
|
|
135
|
+
|
|
136
|
+
See the [Skill performance report](https://apick.app/skills/performance) or call `const { data } = await apick.getSkillPerformance()`. Read sample sizes, dates, methods, machine checks and model scores together. Unmeasured values are `null`; historical results under different conditions are in `legacy`. Model scores are not objective accuracy or sales guarantees.
|
|
137
|
+
|
|
138
|
+
`searchSkills({ sort })` 로 추천(`recommended`)·인기(`popular`)·많이 사용(`used`)·좋아요순(`likes`)·평점순(`rating`)·최신(`new`) 순서를 고르고, 검색·상세 응답의 `usage_label`(사용 건수 구간)·`like_count`·`review_count`·`rating_average` 로 Skill 을 비교할 수 있습니다.
|
|
139
139
|
Pick an order with `searchSkills({ sort })` (`recommended`, `popular`, `used`, `likes`, `rating`, `new`) and compare Skills with `usage_label` (a usage tier), `like_count`, `review_count` and `rating_average` in search and detail responses.
|
|
140
140
|
|
|
141
141
|
`searchSkills({ sort })` 로 추천(`recommended`)·인기(`popular`)·많이 사용(`used`)·좋아요순(`likes`)·평점순(`rating`)·최신(`new`) 순서를 고르고, 검색·상세 응답의 `usage_label`(사용 건수 구간)·`like_count`·`review_count`·`rating_average` 로 Skill 을 비교할 수 있습니다.
|
|
@@ -266,13 +266,13 @@ if (job.data.status === 'completed') {
|
|
|
266
266
|
}
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
접수
|
|
269
|
+
접수 시 최대 요금을 예약하고 완료 후 실제 금액을 확정합니다. 연결 종료는 정상 과금하며 명시 취소는 이미 수행한 유료 처리분을 정산합니다. MP3와 ASS 자막은 각각 한 번 완료 다운로드할 수 있고, 전송 중단 시 다시 시도할 수 있습니다.
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
Submission reserves an upper bound; successful completion settles actual charges. Disconnects do not cancel billing. Explicit cancellation settles work already performed. MP3 and ASS each allow one completed download; interrupted downloads can be retried.
|
|
272
272
|
|
|
273
|
-
|
|
273
|
+
정규화는 기본 켜짐이며 발음을 다듬는 스킬 요금이 추가됩니다. `normalize_text: false`(SDK `normalizeText: false`)로 실행과 요금을 끕니다. 스킬 최종가는 기본요금(판매자 금액·기본 수수료) + AI 원가 × 환율 × 1.4입니다. 정규화 실패는 제작을 중단하며, 서버·공급자의 최종 제작 실패는 정규화까지 전액 환불합니다. ASS에는 원문을 표시합니다.
|
|
274
274
|
|
|
275
|
-
|
|
275
|
+
Normalization is on by default and adds a skill charge. Set `normalize_text: false` (SDK `normalizeText: false`) to skip execution and billing. The skill price is its base fee (seller amount and base commission) plus actual AI cost × the pinned exchange rate × 1.4. Normalization failure stops synthesis; final server/provider failures refund normalization as well. ASS preserves the original spelling.
|
|
276
276
|
|
|
277
277
|
## 신분증 마스킹 / Identity masking
|
|
278
278
|
|
|
@@ -464,3 +464,21 @@ if (status.data.status === "completed") {
|
|
|
464
464
|
### 스킬 결과 파일 / Skill result files
|
|
465
465
|
|
|
466
466
|
`getSkillArtifact(runId, fileId)` returns authenticated binary artifacts. 가격·시간·호출 수 범위와 다운로드 예제: [스킬 파일 가이드 / guide](docs/skill-artifacts.md).
|
|
467
|
+
|
|
468
|
+
## 서브에이전트 / Subagent
|
|
469
|
+
|
|
470
|
+
설치형 `apick-agent` 상품은 `apick-subagent` 스킬 패키지와 전용 REST·MCP를 사용합니다. 원가 +40%, 승인된 동일 결과 캐시 무료, 충전 잔액 외 상품 한도 없음. [연동 가이드](https://apick.app/dev_guide/subagent).
|
|
471
|
+
|
|
472
|
+
The installed `apick-agent` product uses the `apick-subagent` skill package and dedicated REST/MCP interfaces. Confirmed cost plus 40%; approved identical cache reuse is free, with no product quota beyond prepaid balance. [Integration guide](https://apick.app/dev_guide/subagent).
|
|
473
|
+
|
|
474
|
+
```sh
|
|
475
|
+
npx -y apick-mcp --server subagent
|
|
476
|
+
# Local workspace collection / 로컬 파일 수집
|
|
477
|
+
npm install -g apick-subagent
|
|
478
|
+
apick-subagent install
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Set `APICK_API_KEY` in the environment. 원격 MCP는 업로드된 자료를 처리합니다. The remote MCP processes uploaded content; the installed bridge collects local files.
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
TTS: [Gemini · 자동 전환 · 정규화 요금 / fallback and normalization billing](docs/tts.md). `createGeminiTtsJob`, `listGeminiTtsVoices`, `quoteTts`를 지원합니다.
|
package/SECURITY.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Security
|
|
2
|
-
|
|
3
|
-
## API keys
|
|
4
|
-
|
|
5
|
-
Keep APICK API keys in server-side environment variables. Do not commit keys, include them in client-side browser bundles, place them in URLs, or print them in logs.
|
|
6
|
-
|
|
7
|
-
If a key may have been exposed, regenerate it from your APICK account immediately.
|
|
8
|
-
|
|
9
|
-
## Reporting a vulnerability
|
|
10
|
-
|
|
11
|
-
Please report security issues privately through the contact channel listed at <https://apick.app>. Do not open a public issue containing credentials, personal data, or exploit details.
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## API keys
|
|
4
|
+
|
|
5
|
+
Keep APICK API keys in server-side environment variables. Do not commit keys, include them in client-side browser bundles, place them in URLs, or print them in logs.
|
|
6
|
+
|
|
7
|
+
If a key may have been exposed, regenerate it from your APICK account immediately.
|
|
8
|
+
|
|
9
|
+
## Reporting a vulnerability
|
|
10
|
+
|
|
11
|
+
Please report security issues privately through the contact channel listed at <https://apick.app>. Do not open a public issue containing credentials, personal data, or exploit details.
|
package/docs/guide.en.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# apick-api English guide
|
|
2
2
|
|
|
3
|
-
## Skill performance report
|
|
4
|
-
|
|
5
|
-
Use `const { data } = await apick.getSkillPerformance()` to read the [public measurements](https://apick.app/skills/performance). Review sample sizes, dates, methods and failure reasons together. Model scores are not objective accuracy; unmeasured values are `null`. Reading the report does not execute a paid Skill.
|
|
6
|
-
|
|
3
|
+
## Skill performance report
|
|
4
|
+
|
|
5
|
+
Use `const { data } = await apick.getSkillPerformance()` to read the [public measurements](https://apick.app/skills/performance). Review sample sizes, dates, methods and failure reasons together. Model scores are not objective accuracy; unmeasured values are `null`. Reading the report does not execute a paid Skill.
|
|
6
|
+
|
|
7
7
|
## Request and response formats
|
|
8
8
|
|
|
9
9
|
All SDK requests with a body use `multipart/form-data`. Arrays use separate indexed fields such as `utterance_ids[0]`; let the SDK set the Content-Type boundary. GET requests have no body. The server continues accepting older JSON requests for compatibility.
|
|
@@ -94,7 +94,7 @@ TTS supports 14 voice IDs. Use `TTS_VOICE_IDS` and the developer guide for the c
|
|
|
94
94
|
|
|
95
95
|
`v2_ann_m_30s_01`, `v2_ann_m_30s_02`, `v2_ann_m_30s_04`, `v2_ann_m_30s_05`, `v2_ann_f_30s_02`, `v2_ann_f_30s_03`, `v2_ann_f_30s_04`, `v2_ann_f_30s_05`, `v2_m_teen_01`, `v2_m_young_01`, `v2_m_mid_01`, `v2_m_senior_01`, `v2_f_young_01`, `v2_f_senior_01`
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
Normalization is on by default and adds a skill charge. Set `normalize_text: false` (SDK `normalizeText: false`) to skip execution and billing. The skill price is its base fee (seller amount and base commission) plus actual AI cost × the pinned exchange rate × 1.4. Normalization failure stops synthesis; final server/provider failures refund normalization as well. ASS preserves the original spelling.
|
|
98
98
|
|
|
99
99
|
```js
|
|
100
100
|
const screenshot = await client.screenshot('https://example.com');
|
|
@@ -144,7 +144,9 @@ const polished = await client.polish(draftText);
|
|
|
144
144
|
|
|
145
145
|
Text input is limited to 100,000 characters.
|
|
146
146
|
|
|
147
|
-
## Image AI
|
|
147
|
+
## Image AI
|
|
148
|
+
|
|
149
|
+
Under usage billing, external AI costs use confirmed vendor cost × the applicable exchange rate × 1.4. If generation/editing usage cannot be confirmed, HTTP 202 returns `job_id` and `billing_status: "pending"`. The generated output is retained: poll `getImageJob(job_id)` without submitting another generation, then use the existing download methods after settlement.
|
|
148
150
|
|
|
149
151
|
```js
|
|
150
152
|
const result = await client.generateImages('A clean product photo on white', {
|
|
@@ -357,3 +359,6 @@ Skill details and quotes provide estimated price and duration ranges and tool ca
|
|
|
357
359
|
## Product-specific data guides
|
|
358
360
|
|
|
359
361
|
Product-specific authenticated-data guides describe returned fields, source institutions, use cases, and FAQs. An authentication request starts access to the selected product and returns a transactionId for result polling. Request and response contracts and authentication are unchanged. See the [shared authentication guide](https://apick.app/dev_guide/data) for the flow and error handling.
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
TTS: [Gemini · 자동 전환 · 정규화 요금 / fallback and normalization billing](tts.md). `createGeminiTtsJob`, `listGeminiTtsVoices`, `quoteTts`를 지원합니다.
|
package/docs/guide.ko.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# apick-api 한국어 가이드
|
|
2
2
|
|
|
3
|
-
## 스킬 성능표
|
|
4
|
-
|
|
5
|
-
`const { data } = await apick.getSkillPerformance()`로 [공개 측정표](https://apick.app/skills/performance)를 조회합니다. 표본 수·시험일·검사 방법·실패 사유를 함께 확인하세요. 모델 점수는 객관적 정확도가 아니며 미검증 값은 `null`입니다. 조회 자체에는 유료 실행이 필요하지 않습니다.
|
|
6
|
-
|
|
3
|
+
## 스킬 성능표
|
|
4
|
+
|
|
5
|
+
`const { data } = await apick.getSkillPerformance()`로 [공개 측정표](https://apick.app/skills/performance)를 조회합니다. 표본 수·시험일·검사 방법·실패 사유를 함께 확인하세요. 모델 점수는 객관적 정확도가 아니며 미검증 값은 `null`입니다. 조회 자체에는 유료 실행이 필요하지 않습니다.
|
|
6
|
+
|
|
7
7
|
## 요청과 응답 형식
|
|
8
8
|
|
|
9
9
|
SDK의 본문 요청은 모두 `multipart/form-data`입니다. `utterance_ids[0]`처럼 배열을 개별 필드로 전송하며 `Content-Type` 헤더를 직접 지정할 필요가 없습니다. GET 조회는 본문을 보내지 않습니다. 기존 JSON 요청도 서버에서 호환용으로 계속 처리합니다.
|
|
@@ -94,7 +94,7 @@ TTS는 14개 목소리 ID를 지원합니다. 정확한 목록은 `TTS_VOICE_IDS
|
|
|
94
94
|
|
|
95
95
|
`v2_ann_m_30s_01`, `v2_ann_m_30s_02`, `v2_ann_m_30s_04`, `v2_ann_m_30s_05`, `v2_ann_f_30s_02`, `v2_ann_f_30s_03`, `v2_ann_f_30s_04`, `v2_ann_f_30s_05`, `v2_m_teen_01`, `v2_m_young_01`, `v2_m_mid_01`, `v2_m_senior_01`, `v2_f_young_01`, `v2_f_senior_01`
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
정규화는 기본 켜짐이며 발음을 다듬는 스킬 요금이 추가됩니다. `normalize_text: false`(SDK `normalizeText: false`)로 실행과 요금을 끕니다. 스킬 최종가는 기본요금(판매자 금액·기본 수수료) + AI 원가 × 환율 × 1.4입니다. 정규화 실패는 제작을 중단하며, 서버·공급자의 최종 제작 실패는 정규화까지 전액 환불합니다. ASS에는 원문을 표시합니다.
|
|
98
98
|
|
|
99
99
|
```js
|
|
100
100
|
const screenshot = await client.screenshot('https://example.com');
|
|
@@ -144,7 +144,9 @@ const polished = await client.polish(draftText);
|
|
|
144
144
|
|
|
145
145
|
입력 텍스트는 최대 100,000자입니다.
|
|
146
146
|
|
|
147
|
-
## 이미지 AI
|
|
147
|
+
## 이미지 AI
|
|
148
|
+
|
|
149
|
+
새 사용량 요금이 적용되면 외부 AI 판매가는 확인된 원가 × 적용 환율 × 1.4입니다. 생성·편집 응답에서 사용량이 미확정이면 HTTP 202와 `job_id`, `billing_status: "pending"`을 반환합니다. 이미 받은 결과는 보관하므로 재생성하지 말고 `getImageJob(job_id)`로 조회합니다. 정산 완료 후 기존 다운로드 메서드를 사용합니다.
|
|
148
150
|
|
|
149
151
|
```js
|
|
150
152
|
const result = await client.generateImages('흰 배경의 제품 사진', {
|
|
@@ -365,3 +367,6 @@ if (status.data.status === "completed") {
|
|
|
365
367
|
## 상품별 조회 가이드
|
|
366
368
|
|
|
367
369
|
상품별 간편인증 조회 가이드에는 조회 데이터, 출처 기관, 활용 사례와 자주 묻는 질문이 있습니다. 인증 요청은 해당 상품의 자료를 조회하기 위한 단계이며 결과 조회용 transactionId를 반환합니다. 요청·응답 계약과 인증 방식은 동일합니다. [공통 인증 흐름](https://apick.app/dev_guide/data)에서 절차와 오류 처리를 확인하세요.
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
TTS: [Gemini · 자동 전환 · 정규화 요금 / fallback and normalization billing](tts.md). `createGeminiTtsJob`, `listGeminiTtsVoices`, `quoteTts`를 지원합니다.
|
package/docs/subagent.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 서브에이전트 / Subagent
|
|
2
|
+
|
|
3
|
+
`apick-agent`는 설치형 상품이며 `quoteSkill`·`runSkill` 대신 전용 API를 사용합니다. 성공 작업의 확인된 원가에 40%를 가산하며 승인된 동일 결과 캐시는 무료입니다. 충전 잔액 외 상품 사용량 한도는 없습니다.
|
|
4
|
+
|
|
5
|
+
`apick-agent` is an installed-agent product. Use the dedicated API rather than `quoteSkill` or `runSkill`. Successful work is billed at confirmed model cost plus 40%; approved identical-result cache reuse is free. There are no product usage quotas beyond prepaid balance.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import { ApickClient } from 'apick-api';
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
const api = new ApickClient({ apiKey: process.env.APICK_API_KEY });
|
|
11
|
+
const bytes = Buffer.from('검토할 공개 문서입니다.');
|
|
12
|
+
const file = await api.createSubagentFile({
|
|
13
|
+
path: 'docs/sample.txt', bytes: bytes.length,
|
|
14
|
+
sha256: createHash('sha256').update(bytes).digest('hex'), retention: 'seven_days'
|
|
15
|
+
});
|
|
16
|
+
if (file.data.state !== 'ready') {
|
|
17
|
+
for (let offset = 0; offset < bytes.length; offset += file.data.part_bytes) {
|
|
18
|
+
await api.uploadSubagentPart(file.data.file_id, offset / file.data.part_bytes,
|
|
19
|
+
bytes.subarray(offset, offset + file.data.part_bytes).toString('base64'));
|
|
20
|
+
}
|
|
21
|
+
await api.completeSubagentFile(file.data.file_id);
|
|
22
|
+
}
|
|
23
|
+
const job = await api.dispatchSubagent({kind:'summarize', goal:'핵심 내용과 근거를 정리하세요',
|
|
24
|
+
file_ids:[file.data.file_id]}, {idempotencyKey:'sample-summary-20261004-001'});
|
|
25
|
+
const result = await api.collectSubagent(job.data.job_id);
|
|
26
|
+
// 완료 후 evidence_ids를 조회하여 인용·해시를 직접 검토하세요.
|
|
27
|
+
// Once complete, fetch evidence_ids and independently review quotes and hashes.
|
|
28
|
+
console.log(result.data.state);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
접수 응답은 작업 ID를 신속히 반환합니다. 같은 멱등 키와 같은 내용은 기존 작업을 반환하며 내용이 다르면 409입니다. 연결 종료는 취소가 아닙니다. `cancelSubagent`로 명시적으로 취소하세요. `retention:'none'`은 검수 완료 후 삭제하고 임시 보관은 최대 1시간입니다.
|
|
32
|
+
|
|
33
|
+
Submission returns a job ID promptly. Replay the same idempotency key and payload after response loss; a changed payload conflicts with HTTP 409. Disconnecting does not cancel work; use `cancelSubagent`. `retention:'none'` deletes after review, with temporary retention capped at one hour.
|
|
34
|
+
|
|
35
|
+
`subagentUsage`는 호출·토큰·예약·청구·해제·캐시·전송 지표를 반환합니다. 캐시 예상 회피 비용은 동일 작업의 최초 계산 비용 기준이며 주 모델의 실제 청구 절감액이 아닙니다.
|
|
36
|
+
|
|
37
|
+
`subagentUsage` returns calls, tokens, reservations, charges, releases, cache and transfer metrics. Estimated avoided cache cost uses the original job's calculated cost and is not a measured reduction in the main model's bill.
|
|
38
|
+
|
|
39
|
+
[전체 REST·MCP 가이드 / Full guide](https://apick.app/dev_guide/subagent)
|
package/docs/tts.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# TTS · 한국어 안내
|
|
2
|
+
|
|
3
|
+
apick 직접 제작, apick → Gemini 자동 전환, Gemini 직접 제작은 같은 작업 조회·MP3·ASS 다운로드 API를 사용합니다. 파일 구조와 규격은 같으며 음성은 엔진과 목소리에 따라 다릅니다.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
const apick = new ApickClient({ apiKey: process.env.APICK_API_KEY });
|
|
7
|
+
const job = await apick.createTtsJob('기온은 5℃입니다.', {
|
|
8
|
+
voiceId: 'v2_ann_m_30s_01',
|
|
9
|
+
normalizeText: true,
|
|
10
|
+
fallbackPolicy: 'busy',
|
|
11
|
+
fallbackOptions: { voice_id: 'Charon', style: '차분하게' },
|
|
12
|
+
idempotencyKey: 'narration-001'
|
|
13
|
+
});
|
|
14
|
+
const direct = await apick.createGeminiTtsJob({
|
|
15
|
+
voice_id: 'Kore', style: '또렷하게', normalize_text: false,
|
|
16
|
+
utterances: [{ text: '오늘의 이야기입니다.', speaker: '진행자' }]
|
|
17
|
+
}, { idempotencyKey: 'gemini-001' });
|
|
18
|
+
const voices = await apick.listGeminiTtsVoices();
|
|
19
|
+
const quote = await apick.quoteTts({ engine: 'gemini', text: '본문', voice_id: 'Kore' });
|
|
20
|
+
const status = await apick.getTtsJob(job.data.job_id);
|
|
21
|
+
// completed 이후 기존 downloadTtsResult / downloadTtsSubtitles 사용
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| 옵션 | 동작 |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `never` | 기본값. apick 대기열 등록, 가득 차면 429 |
|
|
27
|
+
| `queue_full` | 대기열에도 빈자리가 없을 때 Gemini 전환 |
|
|
28
|
+
| `busy` | 즉시 apick 실행이 불가능하면 Gemini 전환 |
|
|
29
|
+
| `fallbackOptions` | 전환할 때만 적용되는 `voice_id`, `style` |
|
|
30
|
+
| `normalizeText` / `normalize_text` | 기본 true. false는 정규화 스킬 실행·과금 생략 |
|
|
31
|
+
|
|
32
|
+
정규화는 숫자·단위·약어의 문맥에 맞는 발음을 다듬으며, **추가 스킬 요금**이 합산됩니다. 정규화 on 입력 합계(발화 사이 줄바꿈 포함)는 2,000자, Gemini off는 8,000자, apick 기존 입력 한도는 800자입니다. 기본·확장 공개 목소리는 `listGeminiTtsVoices()`로 확인합니다. 자동 선택은 같은 성별의 한국어 목소리를 우선하고 공식 설명 또는 별도 검수로 확인한 연령대와 음색을 비교합니다. `age_basis: catalog_description`은 공식 설명에 적힌 설정 연령이며 실제 화자의 나이를 뜻하지 않습니다. 근거가 없는 목소리는 `age_verified: false`입니다. 대소문자 별칭은 목록에 중복 표시하지 않고 기존 입력도 허용합니다.
|
|
33
|
+
|
|
34
|
+
Gemini 사용 시 목소리와 가격이 달라질 수 있습니다. 실제 AI 원가 × 호출 직전 적용 환율 × 1.4로 판매하고, 스킬은 기본요금(판매자 금액 + 기본 수수료) + AI 사용료입니다. Gemini 100만 토큰당 입력/출력 공급자 가격은 2026-12-31까지 $0.50/$6.00, 2027-01-01 00:00 UTC부터 $1.00/$12.00입니다. $0.54/시간은 출력 참고값이며 과금 단위가 아닙니다.
|
|
35
|
+
|
|
36
|
+
`api.cost`는 접수 예약금을 확정액으로 표시하지 않습니다. `data.billing`의 `synthesis`, `skill`, `total`, `reserved`, `released`, `refunded`, `status`를 확인하세요. `voice_id`는 원래 요청을 보존하고 실제 엔진·모델·목소리는 `synthesis`에 표시합니다. 서버·공급자의 최종 제작 실패는 정규화까지 전액 환불합니다. 클라이언트 연결 종료는 정상 과금하고, 명시 취소는 이미 수행된 유료 처리분을 정산합니다.
|
|
37
|
+
|
|
38
|
+
MP3 24kHz·모노·48kbps와 입력 원문 ASS를 완료 후 24시간 제공합니다. 파일별 한 번 다운로드, 중단 시 재시도가 가능합니다. 동일 요청의 접수 재시도에는 같은 `idempotencyKey`를 사용하세요. 이전 방식 작업의 품질·후보·재개 API는 해당 이전 작업에만 적용됩니다.
|
|
39
|
+
|
|
40
|
+
[개발가이드](https://apick.app/dev_guide/tts) · [정규화 스킬](https://apick.app/skills/korean-text-normalize) · [공식 가격표](https://ai.google.dev/gemini-api/docs/pricing#gemini-3.8-flash-lite-tts)
|
|
41
|
+
|
|
42
|
+
# TTS · English
|
|
43
|
+
|
|
44
|
+
`createTtsJob` supports APICK synthesis and optional Gemini fallback. `createGeminiTtsJob` accepts Gemini voices, style, text or per-speaker utterances. All three paths share `getTtsJob`, `downloadTtsResult`, and `downloadTtsSubtitles`. The MP3/ASS format and response structure match; the generated voices differ.
|
|
45
|
+
|
|
46
|
+
Fallback policies: `never` (default) queues APICK and returns 429 when its queue is full; `queue_full` uses Gemini only when the waiting queue is full; `busy` uses Gemini whenever immediate APICK execution is unavailable. `fallbackOptions.voice_id/style` apply only after fallback. Unsupported explicit voice IDs are rejected. `listGeminiTtsVoices` returns public basic and extended voices without case-alias duplicates, while existing aliases remain accepted. Automatic matching prioritizes Korean voices of the same gender, then the closest supported age band and vocal traits. `age_basis: catalog_description` refers to an age explicitly stated in the official voice description, not a real speaker's biological age. Voices without age evidence remain unverified.
|
|
47
|
+
|
|
48
|
+
Text normalization is **on by default and costs extra**. Set `normalizeText: false` on SDK APICK options or `normalize_text: false` in a request body to skip both the skill and its charge. Normalization allows 2,000 characters across utterances including separating newlines. Gemini without normalization allows 8,000 characters; APICK retains its 800-character limit. The original spelling appears in ASS subtitles.
|
|
49
|
+
|
|
50
|
+
External AI charges equal verified provider cost × the pinned USD/KRW exchange rate × 1.4. A skill adds its base fee once, including seller amount and base commission, without a second markup on AI usage. Gemini provider input/output prices per million tokens are $0.50/$6.00 through December 31, 2026, then $1.00/$12.00 from January 1, 2027, 00:00 UTC. The approximate $0.54/hour figure is informational, not a billing unit. Fallback may change the price and voice.
|
|
51
|
+
|
|
52
|
+
Read the job's `billing` breakdown for reserved, released, captured, and refunded amounts. Submission `api.cost` does not treat a reservation as a final charge. Top-level `voice_id` preserves the APICK request; `synthesis` reports the actual provider/model/voice. Final server/provider failures refund synthesis and normalization. Disconnecting does not cancel background work or billing; explicit cancellation settles work already performed.
|
|
53
|
+
|
|
54
|
+
Results are MP3 (24 kHz, mono, 48 kbps) and ASS, retained for 24 hours after completion. Each file permits one completed download; interrupted transfers may be retried. Reuse the same `idempotencyKey` and input after a lost submission response. Legacy quality/candidate/retry methods apply only to legacy jobs.
|
package/package.json
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "apick-api",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "Official zero-dependency Node.js client for APICK data, AI, and image APIs. 에이픽 데이터·AI·이미지 API 공식 Node.js SDK.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./src/index.cjs",
|
|
7
|
-
"module": "./src/index.js",
|
|
8
|
-
"types": "./src/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./src/index.d.ts",
|
|
12
|
-
"import": "./src/index.js",
|
|
13
|
-
"require": "./src/index.cjs"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"src",
|
|
18
|
-
"docs",
|
|
19
|
-
"examples",
|
|
20
|
-
"README.md",
|
|
21
|
-
"CHANGELOG.md",
|
|
22
|
-
"SECURITY.md",
|
|
23
|
-
"LICENSE"
|
|
24
|
-
],
|
|
25
|
-
"sideEffects": false,
|
|
26
|
-
"engines": {
|
|
27
|
-
"node": ">=18"
|
|
28
|
-
},
|
|
29
|
-
"scripts": {
|
|
30
|
-
"test": "node --test && npm run test:types",
|
|
31
|
-
"test:types": "tsc -p tsconfig.json",
|
|
32
|
-
"test:coverage": "node --test --experimental-test-coverage",
|
|
33
|
-
"prepublishOnly": "npm test"
|
|
34
|
-
},
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"typescript": "^7.0.2"
|
|
37
|
-
},
|
|
38
|
-
"repository": {
|
|
39
|
-
"type": "git",
|
|
40
|
-
"url": "git+https://github.com/lead788/apick-api.git"
|
|
41
|
-
},
|
|
42
|
-
"bugs": {
|
|
43
|
-
"url": "https://github.com/lead788/apick-api/issues"
|
|
44
|
-
},
|
|
45
|
-
"homepage": "https://apick.app/dev_guide",
|
|
46
|
-
"license": "MIT",
|
|
47
|
-
"author": "APICK",
|
|
48
|
-
"publishConfig": {
|
|
49
|
-
"access": "public",
|
|
50
|
-
"provenance": false
|
|
51
|
-
},
|
|
52
|
-
"keywords": [
|
|
53
|
-
"apick",
|
|
54
|
-
"api",
|
|
55
|
-
"sdk",
|
|
56
|
-
"korea",
|
|
57
|
-
"korean-api",
|
|
58
|
-
"business-registry",
|
|
59
|
-
"parcel-tracking",
|
|
60
|
-
"address",
|
|
61
|
-
"ocr",
|
|
62
|
-
"whois",
|
|
63
|
-
"dns",
|
|
64
|
-
"google-search",
|
|
65
|
-
"pdf",
|
|
66
|
-
"excel",
|
|
67
|
-
"tts-jobs",
|
|
68
|
-
"text-summary",
|
|
69
|
-
"image-generation"
|
|
70
|
-
]
|
|
71
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "apick-api",
|
|
3
|
+
"version": "3.11.0",
|
|
4
|
+
"description": "Official zero-dependency Node.js client for APICK data, AI, and image APIs. 에이픽 데이터·AI·이미지 API 공식 Node.js SDK.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.cjs",
|
|
7
|
+
"module": "./src/index.js",
|
|
8
|
+
"types": "./src/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./src/index.d.ts",
|
|
12
|
+
"import": "./src/index.js",
|
|
13
|
+
"require": "./src/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"src",
|
|
18
|
+
"docs",
|
|
19
|
+
"examples",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"SECURITY.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "node --test && npm run test:types",
|
|
31
|
+
"test:types": "tsc -p tsconfig.json",
|
|
32
|
+
"test:coverage": "node --test --experimental-test-coverage",
|
|
33
|
+
"prepublishOnly": "npm test"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^7.0.2"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/lead788/apick-api.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/lead788/apick-api/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://apick.app/dev_guide",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"author": "APICK",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public",
|
|
50
|
+
"provenance": false
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"apick",
|
|
54
|
+
"api",
|
|
55
|
+
"sdk",
|
|
56
|
+
"korea",
|
|
57
|
+
"korean-api",
|
|
58
|
+
"business-registry",
|
|
59
|
+
"parcel-tracking",
|
|
60
|
+
"address",
|
|
61
|
+
"ocr",
|
|
62
|
+
"whois",
|
|
63
|
+
"dns",
|
|
64
|
+
"google-search",
|
|
65
|
+
"pdf",
|
|
66
|
+
"excel",
|
|
67
|
+
"tts-jobs",
|
|
68
|
+
"text-summary",
|
|
69
|
+
"image-generation"
|
|
70
|
+
]
|
|
71
|
+
}
|
package/src/index.cjs
CHANGED
|
@@ -63,7 +63,8 @@ const SERVICES = Object.freeze(Object.fromEntries(
|
|
|
63
63
|
])
|
|
64
64
|
));
|
|
65
65
|
|
|
66
|
-
function
|
|
66
|
+
function normalizeSubagentId(value,prefix){if(typeof value!=='string'||!new RegExp('^'+prefix+'_[a-f0-9]{32}$').test(value))throw new TypeError('Invalid subagent identifier.');return value;}
|
|
67
|
+
function redact(value, apiKey) {
|
|
67
68
|
let text = String(value || '');
|
|
68
69
|
if (apiKey) text = text.split(apiKey).join('***');
|
|
69
70
|
return text.replace(/(Authorization\s*:\s*Bearer\s*)\S+/gi, '$1***').replace(/(CL_AUTH_KEY\s*[:=]\s*)\S+/gi, '$1***');
|
|
@@ -378,15 +379,17 @@ class ApickClient {
|
|
|
378
379
|
Accept: definition.output === 'binary' ? '*/*' : 'application/json',
|
|
379
380
|
Authorization: `Bearer ${this.#apiKey}`
|
|
380
381
|
};
|
|
381
|
-
const method = definition.method || 'POST';
|
|
382
|
+
const method = definition.method || 'POST';
|
|
383
|
+
if (definition.idempotencyKey) headers['X-Idempotency-Key'] = requiredString('idempotencyKey', definition.idempotencyKey, 128);
|
|
382
384
|
const request = {
|
|
383
385
|
method,
|
|
384
386
|
headers,
|
|
385
387
|
signal: controller.signal,
|
|
386
388
|
redirect: 'error'
|
|
387
389
|
};
|
|
388
|
-
if (method !== 'GET') {
|
|
389
|
-
|
|
390
|
+
if (method !== 'GET') {
|
|
391
|
+
if (definition.json) { headers['Content-Type']='application/json'; request.body=JSON.stringify(payload||{}); }
|
|
392
|
+
else request.body = formData || require('./form.cjs').createForm(payload || {}, definition.endpoint);
|
|
390
393
|
}
|
|
391
394
|
|
|
392
395
|
let response;
|
|
@@ -627,13 +630,26 @@ class ApickClient {
|
|
|
627
630
|
return this._call('createVideoJob', null, null, { endpoint:'/rest/'+model+'/jobs/'+jobId+'/result', method:'GET', output:'binary', filename:jobId+'.mp4', timeoutMs:60_000 });
|
|
628
631
|
}
|
|
629
632
|
|
|
630
|
-
createTtsJob(text, options) {
|
|
631
|
-
const config = options || {};
|
|
632
|
-
|
|
633
|
-
voice_id: normalizeTtsVoice(config.voiceId || 'v2_ann_m_30s_01'),
|
|
634
|
-
text: requiredString('text', text, 800)
|
|
635
|
-
}
|
|
636
|
-
|
|
633
|
+
createTtsJob(text, options) {
|
|
634
|
+
const config = options || {};
|
|
635
|
+
const payload = typeof text==='object' && text!==null ? {...text} : {
|
|
636
|
+
voice_id: normalizeTtsVoice(config.voiceId || 'v2_ann_m_30s_01'),
|
|
637
|
+
text: requiredString('text', text, 800)
|
|
638
|
+
};
|
|
639
|
+
if(config.normalizeText!==undefined)payload.normalize_text=config.normalizeText;
|
|
640
|
+
if(config.fallbackPolicy!==undefined)payload.fallback_policy=config.fallbackPolicy;
|
|
641
|
+
if(config.fallbackOptions!==undefined)payload.fallback_options=config.fallbackOptions;
|
|
642
|
+
if(payload.normalize_text!==undefined&&typeof payload.normalize_text!=='boolean')throw new TypeError('normalizeText must be boolean.');
|
|
643
|
+
if(payload.fallback_policy!==undefined&&!['never','queue_full','busy'].includes(payload.fallback_policy))throw new TypeError('Invalid fallbackPolicy.');
|
|
644
|
+
return this._call('createTtsJob',payload,null,{json:typeof text==='object'||config.normalizeText!==undefined||config.fallbackPolicy!==undefined||config.fallbackOptions!==undefined,idempotencyKey:config.idempotencyKey});
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
createGeminiTtsJob(input, options) {
|
|
648
|
+
if(!input||typeof input!=='object'||Array.isArray(input))throw new TypeError('Gemini TTS input is required.');
|
|
649
|
+
return this._call('createTtsJob', input, null, {endpoint:'/rest/tts/gemini/jobs',json:true,idempotencyKey:options?.idempotencyKey});
|
|
650
|
+
}
|
|
651
|
+
listGeminiTtsVoices() { return this._call('createTtsJob',null,null,{endpoint:'/rest/tts/gemini/voices',method:'GET'}); }
|
|
652
|
+
quoteTts(input) { return this._call('createTtsJob',input,null,{endpoint:'/rest/tts/quote',json:true}); }
|
|
637
653
|
|
|
638
654
|
getTtsJob(jobId) {
|
|
639
655
|
const id = normalizeTtsJobId(jobId);
|
|
@@ -949,10 +965,25 @@ class ApickClient {
|
|
|
949
965
|
}
|
|
950
966
|
|
|
951
967
|
getSkillPerformance() {
|
|
952
|
-
return this._skills('GET', '/skills/performance/data.json');
|
|
968
|
+
return this._skills('GET', '/skills/performance/data.json');
|
|
953
969
|
}
|
|
954
970
|
|
|
955
|
-
|
|
971
|
+
_subagent(method, route, options) { return this._skills(method, '/rest/subagent/v1' + route, options); }
|
|
972
|
+
subagentStatus() { return this._subagent('GET', '/status'); }
|
|
973
|
+
subagentUsage() { return this._subagent('GET', '/usage'); }
|
|
974
|
+
createSubagentFile(input) { return this._subagent('POST', '/files', {body: input}); }
|
|
975
|
+
getSubagentFile(fileId) { return this._subagent('GET', '/files/' + normalizeSubagentId(fileId,'saf')); }
|
|
976
|
+
uploadSubagentPart(fileId, partNo, data) { if(!Number.isSafeInteger(partNo)||partNo<0||typeof data!=='string')throw new TypeError('Invalid upload part.');return this._subagent('POST','/files/'+normalizeSubagentId(fileId,'saf')+'/parts',{body:{part_no:partNo,data}}); }
|
|
977
|
+
completeSubagentFile(fileId) { return this._subagent('POST','/files/'+normalizeSubagentId(fileId,'saf')+'/complete',{body:{}}); }
|
|
978
|
+
deleteSubagentFile(fileId) { return this._subagent('DELETE','/files/'+normalizeSubagentId(fileId,'saf')); }
|
|
979
|
+
dispatchSubagent(input, options) { const key=requiredString('idempotencyKey',options?.idempotencyKey,200);if(key.length<8)throw new TypeError('idempotencyKey must contain at least 8 characters.');return this._subagent('POST','/jobs',{body:input,idempotencyKey:key}); }
|
|
980
|
+
collectSubagent(jobId, options) { return this._subagent('GET','/jobs/'+normalizeSubagentId(jobId,'saj'),{query:options?.cursor?{cursor:String(options.cursor)}:{}}); }
|
|
981
|
+
subagentEvidence(jobId,evidenceIds) { return this._subagent('POST','/jobs/'+normalizeSubagentId(jobId,'saj')+'/evidence',{body:{evidence_ids:evidenceIds}}); }
|
|
982
|
+
reviewSubagent(jobId,resultHash,decision) { if(!['accepted','rejected'].includes(decision)||!/^[a-f0-9]{64}$/.test(resultHash))throw new TypeError('Invalid review.');return this._subagent('POST','/jobs/'+normalizeSubagentId(jobId,'saj')+'/review',{body:{result_hash:resultHash,decision}}); }
|
|
983
|
+
cancelSubagent(jobId) { return this._subagent('POST','/jobs/'+normalizeSubagentId(jobId,'saj')+'/cancel',{body:{}}); }
|
|
984
|
+
deleteSubagentJob(jobId) { return this._subagent('DELETE','/jobs/'+normalizeSubagentId(jobId,'saj')); }
|
|
985
|
+
|
|
986
|
+
getSkill(skillId) {
|
|
956
987
|
return this._skills('GET', '/rest/skills/' + normalizeSkillId(skillId));
|
|
957
988
|
}
|
|
958
989
|
|
package/src/index.d.ts
CHANGED
|
@@ -37,7 +37,8 @@ export interface ImageAiOptions { imageCount?: number; size?: ImageAiSize; outpu
|
|
|
37
37
|
export interface ImageAiGenerateOptions extends ImageAiOptions { referenceImage?: string|BinaryInput|ArrayBuffer|ArrayBufferView; referenceFilename?: string; referenceContentType?: 'image/png'|'image/jpeg'|'image/webp'; }
|
|
38
38
|
export interface ImageAiEditOptions extends ImageAiOptions { filename?: string; contentType?: 'image/png'|'image/jpeg'|'image/webp'; }
|
|
39
39
|
export interface ImageAiResultImage { index:number; b64_json:string; mime_type:'image/png'|'image/jpeg'|'image/webp'; width:number; height:number; }
|
|
40
|
-
export interface ImageAiResultData { request_id:string; image_count:number; images:ImageAiResultImage[]; idempotent_replay?:boolean; }
|
|
40
|
+
export interface ImageAiResultData { request_id:string; image_count:number; images:ImageAiResultImage[]; idempotent_replay?:boolean; }
|
|
41
|
+
export interface ImageAiPendingData {request_id:string;job_id:string;status:'processing';billing_status:'pending';reserved_point:number;}
|
|
41
42
|
export interface ImageAiJobData { job_id:string; status:ImageAiStatus; requested_count:number; completed_count?:number; failed_count?:number; prepaid_point?:number; charged_point?:number; refunded_point?:number; result_available?:boolean; expires_at?:string|null; error_code?:ApickImageErrorCode|null; }
|
|
42
43
|
|
|
43
44
|
export interface MaskResidentNumberOptions extends OcrOptions {
|
|
@@ -202,12 +203,23 @@ export interface YoutubeSubtitleOptions { format?: 'vtt' | 'srt' | 'txt'; type?:
|
|
|
202
203
|
export const TTS_VOICE_IDS: readonly [
|
|
203
204
|
'v2_ann_m_30s_01', 'v2_ann_m_30s_02', 'v2_ann_m_30s_04', 'v2_ann_m_30s_05', 'v2_ann_f_30s_02', 'v2_ann_f_30s_03', 'v2_ann_f_30s_04', 'v2_ann_f_30s_05', 'v2_m_teen_01', 'v2_m_young_01', 'v2_m_mid_01', 'v2_m_senior_01', 'v2_f_young_01', 'v2_f_senior_01'
|
|
204
205
|
];
|
|
205
|
-
export type TtsVoiceId = typeof TTS_VOICE_IDS[number];
|
|
206
|
+
export type TtsVoiceId = typeof TTS_VOICE_IDS[number];
|
|
207
|
+
export type TtsFallbackPolicy = 'never' | 'queue_full' | 'busy';
|
|
208
|
+
export interface TtsFallbackOptions { voice_id?: string; style?: string; }
|
|
209
|
+
export interface ApickTtsInput { voice_id: TtsVoiceId; text?: string; utterances?: Array<{text:string;emotion?:string;speed?:number;pause_after_ms?:number}>; normalize_text?:boolean; fallback_policy?:TtsFallbackPolicy; fallback_options?:TtsFallbackOptions; }
|
|
210
|
+
export interface GeminiTtsInput { voice_id?:string; text?:string; style?:string; utterances?:Array<{text:string;voice_id?:string;style?:string;speaker?:string}>; normalize_text?:boolean; language_code?:'ko'|'ko-KR'; }
|
|
211
|
+
export interface TtsOptions { voiceId?:TtsVoiceId; normalizeText?:boolean; fallbackPolicy?:TtsFallbackPolicy; fallbackOptions?:TtsFallbackOptions; idempotencyKey?:string; }
|
|
212
|
+
export interface GeminiTtsVoice { voice_id:string; name:string; gender:string|null; tone:string; age_band:string|null; age_years?:number|null; age_verified?:boolean; age_basis?:'catalog_description'|'reviewed'; age_source?:string; description?:string; language_code?:string|null; reviewed_at?:string; library:string; }
|
|
213
|
+
export interface TtsQuote { synthesis:number; normalization:number; estimated_total:number; maximum:number; synthesis_maximum:number; normalization_maximum:number; estimated_only:true; currency:'POINT'; fallback_price_may_change:boolean; }
|
|
206
214
|
|
|
207
215
|
export interface TtsJobData {
|
|
208
216
|
job_id: string;
|
|
209
217
|
status: 'waiting' | 'processing' | 'completed' | 'cancelled' | 'failed';
|
|
210
|
-
voice_id?:
|
|
218
|
+
voice_id?: string;
|
|
219
|
+
synthesis?: {engine:'apick'|'gemini';model:string;voice_id:string;fallback_reason:string|null;age_verified:boolean;notice:string|null};
|
|
220
|
+
normalization?: {enabled:boolean;run_id:string|null;status:string;skill_id:string|null};
|
|
221
|
+
billing?: {status:string;synthesis:number;skill:number;total:number;reserved:number;refunded:number;released:number;currency:'POINT'};
|
|
222
|
+
expires_at?:string|null;
|
|
211
223
|
character_count?: number;
|
|
212
224
|
result_available?: boolean;
|
|
213
225
|
subtitles_available?: boolean;
|
|
@@ -290,7 +302,10 @@ export class ApickClient {
|
|
|
290
302
|
youtubeThumbnail(url: string): Promise<ApickBinaryResult>;
|
|
291
303
|
youtubeSubtitleList(url: string): Promise<ApickResult<YoutubeSubtitleList>>;
|
|
292
304
|
youtubeSubtitle(url: string, lang: string, options?: YoutubeSubtitleOptions): Promise<ApickBinaryResult>;
|
|
293
|
-
createTtsJob(text: string, options?:
|
|
305
|
+
createTtsJob(text: string | ApickTtsInput, options?: TtsOptions): Promise<ApickResult<TtsJobData>>;
|
|
306
|
+
createGeminiTtsJob(input:GeminiTtsInput, options?:{idempotencyKey?:string}):Promise<ApickResult<TtsJobData>>;
|
|
307
|
+
listGeminiTtsVoices():Promise<ApickResult<{voices:GeminiTtsVoice[];complete:boolean;checked_at:string|null}>>;
|
|
308
|
+
quoteTts(input:(ApickTtsInput|GeminiTtsInput)&{engine?:'apick'|'gemini'}):Promise<ApickResult<TtsQuote>>;
|
|
294
309
|
getTtsJob(jobId: string): Promise<ApickResult<TtsJobData>>;
|
|
295
310
|
cancelTtsJob(jobId: string): Promise<ApickResult<TtsJobData>>;
|
|
296
311
|
downloadTtsResult(jobId: string): Promise<ApickBinaryResult>;
|
|
@@ -302,8 +317,8 @@ export class ApickClient {
|
|
|
302
317
|
jsonToExcel(data: unknown[], options?: { sheetName?: string }): Promise<ApickBinaryResult>;
|
|
303
318
|
summarize(text: string): Promise<ApickResult>;
|
|
304
319
|
polish(text: string): Promise<ApickResult>;
|
|
305
|
-
generateImages(prompt:string, options?:ImageAiGenerateOptions): Promise<ApickResult<ImageAiResultData>>;
|
|
306
|
-
editImages(image:string|BinaryInput|ArrayBuffer|ArrayBufferView, prompt:string, options?:ImageAiEditOptions): Promise<ApickResult<ImageAiResultData>>;
|
|
320
|
+
generateImages(prompt:string, options?:ImageAiGenerateOptions): Promise<ApickResult<ImageAiResultData|ImageAiPendingData>>;
|
|
321
|
+
editImages(image:string|BinaryInput|ArrayBuffer|ArrayBufferView, prompt:string, options?:ImageAiEditOptions): Promise<ApickResult<ImageAiResultData|ImageAiPendingData>>;
|
|
307
322
|
createImageGenerationJob(prompt:string, options?:ImageAiGenerateOptions): Promise<ApickResult<ImageAiJobData>>;
|
|
308
323
|
createImageEditJob(image:string|BinaryInput|ArrayBuffer|ArrayBufferView, prompt:string, options?:ImageAiEditOptions): Promise<ApickResult<ImageAiJobData>>;
|
|
309
324
|
getImageJob(jobId:string): Promise<ApickResult<ImageAiJobData>>;
|
|
@@ -323,9 +338,22 @@ export class ApickClient {
|
|
|
323
338
|
getCashReceiptDeduction(transactionId: string): Promise<ApickResult<DataRequestResult<CashReceiptDeductionResultPayload>>>;
|
|
324
339
|
requestTaxReturnHistory(input: RequestTaxReturnHistoryInput): Promise<ApickResult<DataRequestAcceptedData>>;
|
|
325
340
|
getTaxReturnHistory(transactionId: string): Promise<ApickResult<DataRequestResult<TaxReturnHistoryResultPayload>>>;
|
|
326
|
-
searchSkills(options?: SkillSearchOptions): Promise<ApickResult<SkillPage<SkillSummary>>>;
|
|
327
|
-
/** Public measured results and methods; model scores are not accuracy guarantees. */
|
|
341
|
+
searchSkills(options?: SkillSearchOptions): Promise<ApickResult<SkillPage<SkillSummary>>>;
|
|
342
|
+
/** Public measured results and methods; model scores are not accuracy guarantees. */
|
|
328
343
|
getSkillPerformance(): Promise<ApickResult<SkillPerformanceReport>>;
|
|
344
|
+
subagentStatus(): Promise<ApickResult<Record<string, unknown>>>;
|
|
345
|
+
subagentUsage(): Promise<ApickResult<Record<string, unknown>>>;
|
|
346
|
+
createSubagentFile(input: {path:string;bytes:number;sha256:string;retention?:'seven_days'|'none'}): Promise<ApickResult<SubagentFile>>;
|
|
347
|
+
getSubagentFile(fileId:string): Promise<ApickResult<SubagentFile>>;
|
|
348
|
+
uploadSubagentPart(fileId:string,partNo:number,data:string): Promise<ApickResult<Record<string,unknown>>>;
|
|
349
|
+
completeSubagentFile(fileId:string): Promise<ApickResult<SubagentFile>>;
|
|
350
|
+
deleteSubagentFile(fileId:string): Promise<ApickResult<Record<string,unknown>>>;
|
|
351
|
+
dispatchSubagent(input:SubagentTask,options:{idempotencyKey:string}): Promise<ApickResult<SubagentJob>>;
|
|
352
|
+
collectSubagent(jobId:string,options?:{cursor?:string}): Promise<ApickResult<SubagentJob>>;
|
|
353
|
+
subagentEvidence(jobId:string,evidenceIds:string[]): Promise<ApickResult<Record<string,unknown>>>;
|
|
354
|
+
reviewSubagent(jobId:string,resultHash:string,decision:'accepted'|'rejected'): Promise<ApickResult<Record<string,unknown>>>;
|
|
355
|
+
cancelSubagent(jobId:string): Promise<ApickResult<SubagentJob>>;
|
|
356
|
+
deleteSubagentJob(jobId:string): Promise<ApickResult<Record<string,unknown>>>;
|
|
329
357
|
getSkill(skillId: string): Promise<ApickResult<SkillDetail>>;
|
|
330
358
|
quoteSkill(skillId: string, input: Record<string, unknown>, options?: { version?: string }): Promise<ApickResult<SkillQuote>>;
|
|
331
359
|
runSkill<T = Record<string, unknown>>(skillId: string, input: Record<string, unknown>, options: SkillRunOptions): Promise<ApickResult<SkillRun<T>>>;
|
|
@@ -341,38 +369,38 @@ export const SKILL_CATEGORIES: readonly ['data', 'ai', 'dev', 'document', 'marke
|
|
|
341
369
|
export type SkillCategory = typeof SKILL_CATEGORIES[number];
|
|
342
370
|
/** 검색 순서. 생략하면 등록 순서 / search order; registration order when omitted */
|
|
343
371
|
export const SKILL_SORTS: readonly ['recommended', 'popular', 'used', 'likes', 'rating', 'new', 'mine', 'liked'];
|
|
344
|
-
export type SkillSort = typeof SKILL_SORTS[number];
|
|
345
|
-
export interface SkillPerformanceRate {
|
|
346
|
-
passed: number; total: number; percent: number; interval95: [number, number];
|
|
347
|
-
}
|
|
348
|
-
export interface SkillPerformanceReport {
|
|
349
|
-
schema_version: 1;
|
|
350
|
-
updated_at: string;
|
|
351
|
-
inventory_verified: boolean;
|
|
352
|
-
method: { minimum_cases: number; min_score: number; mean_score: number; min_improvement: number; critical_failures: number; description: string; limitations: string[]; interval_note: string; split: { normal: number; boundary: number; adversarial: number } };
|
|
353
|
-
calibration: { at: string; cases: number; true_positive: number; false_negative: number; false_positive: number; true_negative: number; automatic_release_allowed: boolean } | null;
|
|
354
|
-
additional_calibrations: Array<{ label: string; at: string; cases: number; detected: number; missed: number; false_positive: number; uncertain: number; automatic_release_allowed: boolean; scope: string }>;
|
|
355
|
-
skills: Array<{
|
|
356
|
-
key: string; title: string; group: string; origin: 'new' | 'existing'; published: boolean | null; url: string | null;
|
|
357
|
-
current: {
|
|
358
|
-
state: 'not_tested' | 'partial' | 'held' | 'passed' | 'stale'; at?: string;
|
|
359
|
-
cases: number; planned_cases: number; score: number | null; baseline_score: number | null;
|
|
360
|
-
score_samples?: number; evaluation_errors?: number;
|
|
361
|
-
delivery: SkillPerformanceRate | null; machine: SkillPerformanceRate | null;
|
|
362
|
-
median_seconds: number | null; p95_seconds: number | null; timing_samples?: number;
|
|
363
|
-
reasons: string[]; method?: string; sample_type?: string;
|
|
364
|
-
baseline_format_valid?: boolean;
|
|
365
|
-
evaluation_stage?: 'preliminary' | 'holdout';
|
|
366
|
-
dataset_composition?: { normal: number; boundary: number; adversarial: number; misplaced_rejections: number; valid: boolean };
|
|
367
|
-
min_score?: number | null; critical_cases?: number | null;
|
|
368
|
-
case_split?: { standard: number; boundary: number; adversarial: number };
|
|
369
|
-
extra_checks?: Array<{ name: string; passed: number; total: number }>;
|
|
370
|
-
tool_calls?: Array<{ label: string; samples: number; total: number | null; median: number | null; p95: number | null }>;
|
|
371
|
-
case_results?: Array<{ index: number; name: string; kind: 'standard' | 'boundary' | 'adversarial'; status: 'tested' | 'evaluation_error' | 'machine_only' | 'not_tested'; expected: 'success' | 'reject' | null; machine_pass: boolean; score: number | null; baseline_score: number | null; failed_checks: string[]; reason: string | null }>;
|
|
372
|
-
};
|
|
373
|
-
legacy: { cases: number; score: number; baseline_score: number; method: string; independent_holdout: false; at?: string } | null;
|
|
374
|
-
}>;
|
|
375
|
-
}
|
|
372
|
+
export type SkillSort = typeof SKILL_SORTS[number];
|
|
373
|
+
export interface SkillPerformanceRate {
|
|
374
|
+
passed: number; total: number; percent: number; interval95: [number, number];
|
|
375
|
+
}
|
|
376
|
+
export interface SkillPerformanceReport {
|
|
377
|
+
schema_version: 1;
|
|
378
|
+
updated_at: string;
|
|
379
|
+
inventory_verified: boolean;
|
|
380
|
+
method: { minimum_cases: number; min_score: number; mean_score: number; min_improvement: number; critical_failures: number; description: string; limitations: string[]; interval_note: string; split: { normal: number; boundary: number; adversarial: number } };
|
|
381
|
+
calibration: { at: string; cases: number; true_positive: number; false_negative: number; false_positive: number; true_negative: number; automatic_release_allowed: boolean } | null;
|
|
382
|
+
additional_calibrations: Array<{ label: string; at: string; cases: number; detected: number; missed: number; false_positive: number; uncertain: number; automatic_release_allowed: boolean; scope: string }>;
|
|
383
|
+
skills: Array<{
|
|
384
|
+
key: string; title: string; group: string; origin: 'new' | 'existing'; published: boolean | null; url: string | null;
|
|
385
|
+
current: {
|
|
386
|
+
state: 'not_tested' | 'partial' | 'held' | 'passed' | 'stale'; at?: string;
|
|
387
|
+
cases: number; planned_cases: number; score: number | null; baseline_score: number | null;
|
|
388
|
+
score_samples?: number; evaluation_errors?: number;
|
|
389
|
+
delivery: SkillPerformanceRate | null; machine: SkillPerformanceRate | null;
|
|
390
|
+
median_seconds: number | null; p95_seconds: number | null; timing_samples?: number;
|
|
391
|
+
reasons: string[]; method?: string; sample_type?: string;
|
|
392
|
+
baseline_format_valid?: boolean;
|
|
393
|
+
evaluation_stage?: 'preliminary' | 'holdout';
|
|
394
|
+
dataset_composition?: { normal: number; boundary: number; adversarial: number; misplaced_rejections: number; valid: boolean };
|
|
395
|
+
min_score?: number | null; critical_cases?: number | null;
|
|
396
|
+
case_split?: { standard: number; boundary: number; adversarial: number };
|
|
397
|
+
extra_checks?: Array<{ name: string; passed: number; total: number }>;
|
|
398
|
+
tool_calls?: Array<{ label: string; samples: number; total: number | null; median: number | null; p95: number | null }>;
|
|
399
|
+
case_results?: Array<{ index: number; name: string; kind: 'standard' | 'boundary' | 'adversarial'; status: 'tested' | 'evaluation_error' | 'machine_only' | 'not_tested'; expected: 'success' | 'reject' | null; machine_pass: boolean; score: number | null; baseline_score: number | null; failed_checks: string[]; reason: string | null }>;
|
|
400
|
+
};
|
|
401
|
+
legacy: { cases: number; score: number; baseline_score: number; method: string; independent_holdout: false; at?: string } | null;
|
|
402
|
+
}>;
|
|
403
|
+
}
|
|
376
404
|
export type SkillRunStatus = 'queued' | 'running' | 'completing' | 'succeeded' | 'failed' | 'timed_out' | 'cancelled';
|
|
377
405
|
export type SkillBillingStatus = 'reserved' | 'captured' | 'released' | 'partially_refunded' | 'refunded';
|
|
378
406
|
export type SkillFailureCode = 'EXECUTION_FAILED' | 'OUTPUT_INVALID' | 'TIMED_OUT' | 'CANCELLED' | 'UPSTREAM_UNAVAILABLE';
|
|
@@ -408,7 +436,7 @@ export interface SkillSummary {
|
|
|
408
436
|
/** 실행마다 같은 기본 금액 / base amount charged on every run */
|
|
409
437
|
price_points: number;
|
|
410
438
|
/** 사용량까지 더한 예상 금액 / estimated amount including usage */
|
|
411
|
-
estimated_points: number;
|
|
439
|
+
estimated_points: number | null;
|
|
412
440
|
/** true 면 실행마다 실제 사용량만큼 금액이 달라집니다 / amount varies per run with actual usage */
|
|
413
441
|
usage_priced: boolean;
|
|
414
442
|
seller: { name: string }; uses_generative_ai: boolean;
|
|
@@ -420,7 +448,9 @@ export interface SkillSummary {
|
|
|
420
448
|
rating_average: number | null;
|
|
421
449
|
}
|
|
422
450
|
export interface SkillDetail extends SkillSummary {
|
|
423
|
-
description: string; billing_rule: 'validated_result'; limits: SkillLimits;
|
|
451
|
+
description: string; billing_rule: 'validated_result' | 'subagent_usage'; limits: SkillLimits | null;
|
|
452
|
+
delivery?: 'installed_agent'; installation?: {package:string;command:string;api_key_env:string;guide:string;usage:string};
|
|
453
|
+
billing?: {markup_percent:number;installation_points:number;base_points:number;complete_cache_points:number;quota:null};
|
|
424
454
|
input_schema: Record<string, unknown>; output_schema: Record<string, unknown>;
|
|
425
455
|
examples: unknown[]; stats: Record<string, unknown> | null; published_at: string | null;
|
|
426
456
|
}
|
|
@@ -480,3 +510,7 @@ export interface VideoJobData {
|
|
|
480
510
|
result_expires_at?: string | null; idempotent_replay?: boolean;
|
|
481
511
|
error?: { code: string; message: string };
|
|
482
512
|
}
|
|
513
|
+
|
|
514
|
+
export interface SubagentTask { kind:'inventory'|'extract'|'summarize'|'compare';goal:string;file_ids:string[];focus?:string[];acceptance?:string[];retention?:'seven_days'|'none'; }
|
|
515
|
+
export interface SubagentFile { file_id:string;path:string;sha256:string;bytes:number;state:string;expires_at:string;part_bytes?:number; }
|
|
516
|
+
export interface SubagentJob { job_id:string;kind:SubagentTask['kind'];state:string;billing_state:string;cache_hit:boolean;reserved_points:number;charged_points:number;accrued_points:string;result_hash?:string;result?:Record<string,unknown>; }
|