@kaydash9999/banker-plugins 0.20.2 → 0.21.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +203 -1
- package/PRIVACY.md +34 -4
- package/README.md +46 -15
- package/bin/banker.js +228 -51
- package/bin/lib/codex-hooks.mjs +249 -0
- package/bin/lib/telemetry-config.mjs +33 -16
- package/codex/manifest.json +14 -11
- package/codex/skills/graceful-pause/SKILL.md +30 -0
- package/codex/skills/progress/SKILL.md +42 -0
- package/codex/skills/progress/scripts/progress-plan.mjs +722 -0
- package/codex/skills/progress/scripts/progress.mjs +295 -0
- package/codex/transform-matrix.md +19 -14
- package/commands/setup.md +23 -0
- package/hooks/obsidize-hook.mjs +116 -4
- package/hooks/progress-plan.mjs +1 -1
- package/hooks/progress.mjs +143 -38
- package/hooks/register.mjs +13 -3
- package/hooks/telemetry-count-codex.mjs +222 -0
- package/hooks/update-checkin.mjs +15 -7
- package/hooks/update-fetch.mjs +15 -9
- package/hooks/update-notify.mjs +30 -17
- package/package.json +1 -1
- package/skills/3d-intro-build/SKILL.md +11 -5
- package/skills/3d-intro-build/references/azure-adapter.mjs +374 -81
- package/skills/3d-intro-build/references/curate.mjs +48 -14
- package/skills/3d-intro-build/references/preview-lib.mjs +51 -15
- package/skills/3d-intro-build/references/prompts.md +4 -4
- package/skills/3d-intro-build/references/serve.mjs +6 -1
- package/skills/3d-intro-build/references/verify-intro.mjs +16 -9
- package/skills/3d-intro-build/references/video-pool.mjs +250 -135
- package/skills/3d-intro-setup/SKILL.md +41 -10
- package/skills/3d-intro-setup/references/azure-adapter.mjs +374 -81
- package/skills/3d-intro-setup/references/video-pool.mjs +250 -135
- package/skills/anti-drm/SKILL.md +6 -3
- package/skills/anti-drm/scripts/anti-drm.mjs +49 -12
- package/skills/anti-drm/scripts/instruction-toggle.mjs +105 -20
- package/skills/append_wiki/SKILL.md +34 -8
- package/skills/audit-mock/SKILL.md +1 -1
- package/skills/audit-security/SKILL.md +64 -2
- package/skills/compact-wiki/SKILL.md +37 -6
- package/skills/deep-research/SKILL.md +11 -0
- package/skills/docs-setup/SKILL.md +37 -7
- package/skills/lfm/SKILL.md +148 -0
- package/skills/lineage/SKILL.md +25 -15
- package/skills/lineage/lineage.py +564 -301
- package/skills/motion-graphic-make/SKILL.md +1 -1
- package/skills/motion-graphic-make/references/curate.mjs +48 -14
- package/skills/motion-graphic-make/references/preview-lib.mjs +51 -15
- package/skills/motion-graphic-make/references/serve.mjs +6 -1
- package/skills/motion-graphic-setup/SKILL.md +58 -13
- package/skills/obsidizer/SKILL.md +30 -11
- package/skills/obsidizer/obsidize.mjs +50 -12
- package/skills/omc-patch/SKILL.md +86 -23
- package/skills/omc-patch/scripts/omc-patch.mjs +460 -116
- package/skills/payload-mon/SKILL.md +6 -2
- package/skills/payload-mon/scripts/payload-mon.mjs +88 -12
- package/skills/payload-mon/scripts/payload-size.mjs +4 -1
- package/skills/pdf-vision-extract/SKILL.md +11 -6
- package/skills/ralph-qa/SKILL.md +125 -151
- package/skills/ralph-qa/references/gemini-seat.mjs +67 -19
- package/skills/ralph-qa/references/payload-scan.mjs +22 -7
- package/skills/ralph-qa/references/seat-payload.mjs +646 -0
- package/skills/ralph-qa/references/seat-run.mjs +956 -0
- package/skills/ralph-qa/references/seat-spawn.mjs +205 -0
- package/skills/ralph-qa/references/verifier-probe.mjs +57 -16
- package/skills/rfp-author/SKILL.md +5 -3
- package/skills/rfp-author/references/vendor-rfp-structure.md +1 -1
- package/skills/setup-bypass-permissions/SKILL.md +27 -9
- package/skills/setup-bypass-permissions/scripts/codex-bypass.mjs +135 -0
- package/skills/setup-bypass-permissions/scripts/codex-config.mjs +210 -0
- package/skills/setup-harness-factory/SKILL.md +17 -1
- package/skills/setup-insane-search/SKILL.md +16 -0
- package/skills/setup-java/SKILL.md +20 -1
- package/skills/setup-lsp/SKILL.md +56 -13
- package/skills/setup-mcp/SKILL.md +73 -4
- package/skills/setup-node/SKILL.md +31 -6
- package/skills/setup-omc/SKILL.md +24 -0
- package/skills/setup-omc-hud/SKILL.md +42 -9
- package/skills/setup-omc-hud/assets/apply-hud.mjs +242 -27
- package/skills/setup-omc-hud/assets/codex-config.mjs +210 -0
- package/skills/setup-omc-hud/assets/codex-status-line.mjs +90 -0
- package/skills/setup-omc-hud/assets/omc-hud-custom.mjs +81 -14
- package/skills/setup-omc-hud/scripts/claude-update-last.mjs +5 -3
- package/skills/setup-playwright/SKILL.md +45 -2
- package/skills/setup-pwsh/SKILL.md +19 -0
- package/skills/setup-python/SKILL.md +45 -7
- package/skills/setup-sandbox/SKILL.md +30 -5
- package/skills/setup-stitch/SKILL.md +22 -0
- package/skills/setup-tmux/SKILL.md +24 -4
- package/skills/smart-compact/SKILL.md +58 -12
- package/skills/smart-compact/scripts/codex-gate.mjs +384 -0
- package/skills/tone-compact/SKILL.md +2 -1
- package/skills/tone-compact/scripts/instruction-toggle.mjs +105 -20
- package/skills/ultra-chain/SKILL.md +12 -7
- package/skills/ultra-chain/references/preview-lib.mjs +51 -15
- package/skills/ultra-chain/references/serve.mjs +6 -1
- package/skills/ultra-interview/SKILL.md +14 -2
- package/skills/update-banker/SKILL.md +19 -3
- package/skills/vertical-pptx/SKILL.md +6 -3
- package/skills/vertical-pptx-setup/SKILL.md +76 -20
package/hooks/update-fetch.mjs
CHANGED
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
* 자체는 캐시만 읽는 별도 훅이 담당한다(이 파일은 네트워크 조회만 - 화면 출력 없음).
|
|
6
6
|
*
|
|
7
7
|
* fail-closed 규약(각 항목은 update-fetch.test.mjs 가 검증한다):
|
|
8
|
-
* -
|
|
8
|
+
* - 마지막 성공(checkedAt)이나 마지막 실패한 시도(triedAt)에서 하루가 지나지 않았으면 무동작(updateCheckDue).
|
|
9
9
|
* - 비-https 는 loopback(localhost/127.0.0.1/::1) 에서만 http 허용, 그 외 비-https 는 거부.
|
|
10
10
|
* - 3xx 리다이렉트는 따라가지 않고 no-op.
|
|
11
|
-
* -
|
|
11
|
+
* - 무활동 10초 timeout 과 요청마다 30초 교환 전체 마감으로 hang 하지 않는다.
|
|
12
|
+
* - 응답 본문은 256KiB 까지만 모은다. 넘으면 연결을 끊고 그 응답을 쓰지 않는다.
|
|
13
|
+
* - 응답 JSON 에서 version 문자열만 방어 추출. 버전을 얻지 못하면(조회 실패, 거부, 없거나 비문자열) 시도 시각
|
|
14
|
+
* (triedAt)만 써서 하루를 쉰다. latest 와 checkedAt 은 쓰지 않는다.
|
|
12
15
|
* - 캐시는 writeUpdateCache 로 병합 기록: fetch 된 latest 가 기존 캐시와 다르면 notified 를 초기화
|
|
13
16
|
* (재무장)하고, 같으면 형제 필드(notified 등)를 patch 에서 생략해 그대로 보존한다.
|
|
14
17
|
* - 어떤 오류도 삼키고 항상 exit 0. GET 뿐이라 페이로드/식별자 전송이 없다.
|
|
@@ -19,7 +22,7 @@ import http from 'node:http';
|
|
|
19
22
|
import https from 'node:https';
|
|
20
23
|
|
|
21
24
|
import {
|
|
22
|
-
UPDATE_CHECK_PATH,
|
|
25
|
+
UPDATE_CHECK_PATH, NPM_LATEST_URL, writeUpdateCache, collectBody, netDeadlineMs, readRegular, updateCheckDue,
|
|
23
26
|
} from '../bin/lib/telemetry-config.mjs';
|
|
24
27
|
|
|
25
28
|
const NET_TIMEOUT_MS = 10_000;
|
|
@@ -45,7 +48,8 @@ function readCache() {
|
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
// url 에 GET 요청해 응답 JSON 의 version 문자열만 추출한다. 실패·거부·리다이렉트·malformed 는 전부
|
|
48
|
-
// null. reject 하지 않고 항상 resolve 한다(
|
|
51
|
+
// null. reject 하지 않고 항상 resolve 한다(무활동 timeout 과 교환 전체 마감, 본문 256KiB 상한). GET 뿐이라
|
|
52
|
+
// 페이로드·식별자 헤더가 없다.
|
|
49
53
|
function fetchLatestVersion(url) {
|
|
50
54
|
return new Promise((resolvePromise) => {
|
|
51
55
|
let done = false;
|
|
@@ -94,21 +98,23 @@ function fetchLatestVersion(url) {
|
|
|
94
98
|
|
|
95
99
|
async function main() {
|
|
96
100
|
const cache = readCache();
|
|
97
|
-
|
|
98
|
-
if (checkedAt !== null && (Date.now() - checkedAt) < UPDATE_THROTTLE_MS) return; // throttle 미경과 - no-op.
|
|
101
|
+
if (!updateCheckDue(cache)) return; // 성공이나 실패한 시도에서 하루가 지나지 않음 - no-op.
|
|
99
102
|
|
|
100
103
|
const url = process.env.BANKER_NPM_URL || NPM_LATEST_URL; // 테스트 주입용 override.
|
|
101
104
|
const latest = await fetchLatestVersion(url);
|
|
102
|
-
if (!latest)
|
|
105
|
+
if (!latest) { // 조회 실패·거부·malformed - 버전은 쓰지 않고 시도 시각만 남겨 하루를 쉰다.
|
|
106
|
+
writeUpdateCache({ triedAt: Date.now() });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
103
109
|
|
|
104
110
|
// 개인화 매니페스트는 여기서 조회하지 않는다: update-fetch 는 카운팅 opt-out(countingActive false) 경로의
|
|
105
111
|
// fetcher 이고, 개인화 표시도 countingActive() 로 게이트되므로 이 경로에선 표시될 일이 없다. 매니페스트
|
|
106
112
|
// 조회는 카운팅 활성 경로의 update-checkin 만 수행한다(중복·죽은 조회 제거).
|
|
107
113
|
const cachedLatest = typeof cache.latest === 'string' ? cache.latest : null;
|
|
108
114
|
if (cachedLatest !== latest) {
|
|
109
|
-
writeUpdateCache({ latest, checkedAt: Date.now(), notified: null }); // 신버전 - notified 재무장.
|
|
115
|
+
writeUpdateCache({ latest, checkedAt: Date.now(), notified: null, triedAt: null }); // 신버전 - notified 재무장. 남은 실패 시도 시각은 비움.
|
|
110
116
|
} else {
|
|
111
|
-
writeUpdateCache({ latest, checkedAt: Date.now() }); // 동일 버전 - notified 등 형제 필드는 병합
|
|
117
|
+
writeUpdateCache({ latest, checkedAt: Date.now(), triedAt: null }); // 동일 버전 - notified 등 형제 필드는 병합 보존, 실패 시도 시각은 비움.
|
|
112
118
|
}
|
|
113
119
|
}
|
|
114
120
|
|
package/hooks/update-notify.mjs
CHANGED
|
@@ -19,9 +19,10 @@ import { dirname, join } from 'node:path';
|
|
|
19
19
|
import { fileURLToPath } from 'node:url';
|
|
20
20
|
|
|
21
21
|
import {
|
|
22
|
-
UPDATE_CHECK_PATH,
|
|
22
|
+
UPDATE_CHECK_PATH, updateCheckDue,
|
|
23
23
|
noUpdateCheck, countingActive, endpoint,
|
|
24
24
|
installedVersion, compareVersions, writeUpdateCache, readUsedSkills, readRegular,
|
|
25
|
+
CODEX_SHAPE_MISS_PATH, writeByRename,
|
|
25
26
|
} from '../bin/lib/telemetry-config.mjs';
|
|
26
27
|
|
|
27
28
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
@@ -65,7 +66,11 @@ function personalizedSkills(cached) {
|
|
|
65
66
|
// (기존 동작). banker: 접두는 떼서 짧게. 이모지/em-dash 없음(사용자 가시 채널).
|
|
66
67
|
function buildMessage(latest, installed, cached) {
|
|
67
68
|
const head = `banker ${latest} 사용 가능 (현재 ${installed}).`;
|
|
68
|
-
|
|
69
|
+
// Codex 의 훅은 --codex 를 받는다(banker setup --codex 가 설치). Codex 에는 /banker: 명령이 없어 스킬 이름과
|
|
70
|
+
// npm 뒤의 Codex 설치 명령을 안내한다.
|
|
71
|
+
const tail = process.argv.includes('--codex')
|
|
72
|
+
? `업데이트: $banker-update-banker 또는 npm i -g ${NPM_PKG} 뒤 banker setup --codex`
|
|
73
|
+
: `업데이트: /banker:update-banker 또는 npm i -g ${NPM_PKG}`;
|
|
69
74
|
const hits = personalizedSkills(cached);
|
|
70
75
|
if (hits.length) {
|
|
71
76
|
const names = hits.slice(0, 5).map((s) => s.replace(/^banker:/, '')).join(', ');
|
|
@@ -79,21 +84,26 @@ function buildMessage(latest, installed, cached) {
|
|
|
79
84
|
// compareVersions null(미확정·malformed)·구버전·동일 → 무고지. 고지 후 notified 를 기록해 재고지를 막는다.
|
|
80
85
|
// 고지 문구는 buildMessage 가 만든다(로컬 changedSkills∩써본스킬이 있으면 개인화, 없으면 일반).
|
|
81
86
|
function maybeNotify(cached) {
|
|
82
|
-
if (!cached) return;
|
|
87
|
+
if (!cached) return '';
|
|
83
88
|
const installed = installedVersion();
|
|
84
89
|
const cmp = compareVersions(cached.latest, installed);
|
|
85
|
-
if (cmp === null || cmp <= 0) return; // 미확정/구/동일 → 무고지
|
|
86
|
-
if (cached.notified === cached.latest) return; // 이미 고지한 버전 → dedupe
|
|
87
|
-
const msg = buildMessage(cached.latest, installed, cached);
|
|
88
|
-
process.stdout.write(JSON.stringify({ systemMessage: msg }));
|
|
90
|
+
if (cmp === null || cmp <= 0) return ''; // 미확정/구/동일 → 무고지
|
|
91
|
+
if (cached.notified === cached.latest) return ''; // 이미 고지한 버전 → dedupe
|
|
89
92
|
writeUpdateCache({ notified: cached.latest }); // 형제 필드(latest/checkedAt/changedSkills) 보존하며 notified 만 병합.
|
|
93
|
+
return buildMessage(cached.latest, installed, cached);
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
// Codex: 사용량 카운팅 훅이 이 Codex 판의 기록 형식을 읽지 못했으면(codex-shape-miss.json) 한 번 알린다.
|
|
97
|
+
// 카운트가 조용히 0 으로 남지 않게 하려는 것이다. 업데이트 확인을 끈 사용자에게도 알린다.
|
|
98
|
+
export function shapeMissNotice() {
|
|
99
|
+
try {
|
|
100
|
+
const miss = JSON.parse(readRegular(CODEX_SHAPE_MISS_PATH));
|
|
101
|
+
if (!miss || typeof miss.version !== 'string' || miss.notified) return '';
|
|
102
|
+
writeByRename(CODEX_SHAPE_MISS_PATH, JSON.stringify({ version: miss.version, notified: true }));
|
|
103
|
+
return `banker 사용량 카운팅이 Codex ${miss.version.slice(0, 40)} 의 기록 형식을 읽지 못함. $banker-update-banker 로 banker 를 업데이트하고, 그래도 같으면 알려 주십시오`;
|
|
104
|
+
} catch {
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
// 갱신 fetcher 절대경로 결정: count-default-on 활성(countingActive) + 엔드포인트 설정 시
|
|
@@ -117,11 +127,14 @@ async function main() {
|
|
|
117
127
|
// SessionStart payload 를 드레인(파이프 위생). 내용을 쓰지 않으므로 파싱 실패해도 무해.
|
|
118
128
|
try { await readStdin(); } catch { /* stdin 없음/오류 무해 */ }
|
|
119
129
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
const notes = process.argv.includes('--codex') ? [shapeMissNotice()] : [];
|
|
131
|
+
if (!noUpdateCheck()) { // opt-out 이면 업데이트 확인만 무동작.
|
|
132
|
+
const cached = readCache(); // 포그라운드는 캐시 읽기만(네트워크 없음).
|
|
133
|
+
notes.unshift(maybeNotify(cached));
|
|
134
|
+
if (updateCheckDue(cached)) spawnFetcher(); // 갱신은 백그라운드로 위임. 실패한 시도(triedAt)에서도 하루를 쉰다.
|
|
135
|
+
}
|
|
136
|
+
const msg = notes.filter(Boolean).join('\n');
|
|
137
|
+
if (msg) process.stdout.write(JSON.stringify({ systemMessage: msg }));
|
|
125
138
|
}
|
|
126
139
|
|
|
127
140
|
// 직접 실행(훅)일 때만 main() 을 돌린다. import(테스트)시엔 chooseFetcher 만 노출하고 main 은 미실행.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaydash9999/banker-plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "banker — Claude Code + Codex CLI plugin (QA, audit, docs, architecture, wiki skills). Install via Claude Code marketplace, or `npm i -g @kaydash9999/banker-plugins` then `banker setup`.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"banker": "bin/banker.js"
|
|
@@ -52,9 +52,11 @@ import { resolveCreds, resolveFfmpeg } from './references/azure-adapter.mjs';
|
|
|
52
52
|
const creds = resolveCreds({ projectDir }); // _source === null 이면 미설정
|
|
53
53
|
// ffmpeg 경로는 resolveFfmpeg 가 셸의 FFMPEG_PATH 와 홈의 설정 파일, 키 파일에서만 찾는다. 프로젝트 키 파일의 값은 쓰지 않는다.
|
|
54
54
|
if (creds._ignored) console.log('프로젝트 키 파일에서 쓰지 않는 값:', Object.keys(creds._ignored).join(', ')); // 값은 출력하지 않는다
|
|
55
|
+
if (creds._tracked) throw new Error(`프로젝트 키 파일을 git 이 추적한다: ${creds._source}`); // 아래 첫 항목. generateClip 도 거부한다
|
|
55
56
|
```
|
|
56
57
|
|
|
57
58
|
- `creds._source` 가 `null` 이면 크리덴셜이 없다. `3d-intro-setup` 으로 보낸다.
|
|
59
|
+
- `creds._tracked` 가 참이면 프로젝트 키 파일을 git 이 추적한다. 멈추고 사람에게 알린다. 그 값은 저장소에서 왔을 수 있고(endpoint 가 프롬프트와 프레임을 받는 곳이다), 키를 적으면 다음 커밋에 실린다. `git rm --cached .env.3d-intro.local` 로 추적을 풀거나 홈 키 파일을 쓴다.
|
|
58
60
|
- `creds._ignored` 가 있으면 프로젝트 키 파일의 `FFMPEG_PATH` 를 쓰지 않은 것이다. 저장소와 함께 온 파일이 실행할 프로그램을 정하지 못하게 막은 것이다. 값은 출력하지 않으니 사람이 파일을 열어 확인하고, 그 경로가 필요하면 `3d-intro-setup` §2 로 홈 설정 파일에 남긴다.
|
|
59
61
|
Claude Code: `/banker:setup` 에서 3d-intro-setup / Codex: `banker-3d-intro-setup`.
|
|
60
62
|
- `resolveFfmpeg()` 가 throw 하면 ffmpeg 가 없다. 같은 `3d-intro-setup` 으로 보낸다.
|
|
@@ -64,6 +66,7 @@ if (creds._ignored) console.log('프로젝트 키 파일에서 쓰지 않는 값
|
|
|
64
66
|
쉬는 키를 바로 다시 쓰려면 `resetPoolState({ creds, labels: ['WAN_2'] })` 로 그 키의 기록을 지운다(`labels` 를 빼면 전체). 서버의 `Retry-After` 는 1초에서 10분 사이로만 받는다.
|
|
65
67
|
`malformed` 는 endpoint 가 https URL 이 아니거나(http 는 이 기기의 localhost 만 허용) 모델이 한 id 가 아닌 항목이다(`reason` 이 `endpoint` 또는 `model`). 영상 단계는 이 항목을 건너뛰고, 모두 `malformed` 면 영상 단계에서 멈춘다. 그러니 유료 스틸을 만들기 전에 사용자에게 알리고 `3d-intro-setup` 으로 고친다.
|
|
66
68
|
Azure 호출도 같다. 키는 https 로만 보내고, `http://` endpoint 는 보내기 전에 막는다(Sora 영상 단계는 `invalid_request`, 이미지 생성 같은 그 밖의 호출은 `HTTP 0 (EINSECURE)` 오류).
|
|
69
|
+
이 기기의 `http://` 로 키를 보낼 때도 Node 가 env 프록시(`NODE_USE_ENV_PROXY=1`, `--use-env-proxy`)로 http 를 보내면 보내기 전에 막는다(`EPROXYKEY`). `NO_PROXY` 에 그 호스트나 `호스트:포트` 를 그대로 적으면(`no_proxy` 도 있으면 그쪽에도) 직접 보낸다. 영상 단계는 그런 WAN 항목을 보내기 전에 건너뛰고, 모든 항목이 그렇거나 Sora endpoint 가 그렇다면 Sora 로 넘어가지 않고 `invalid_request` 로 멈춘다.
|
|
67
70
|
WAN 항목(`WAN_<n>_ENDPOINT`, `WAN_<n>_API_KEY`)이 하나도 없으면 영상은 처음부터 Sora 로 만든다. 이때 정지와 비행 모드(Step 4B)는 쓸 수 없다.
|
|
68
71
|
- 독립 검증(Step 6)에는 Node 용 playwright 패키지와 Chromium 이 필요하다. `npx playwright install chromium`(`setup-playwright`)은 브라우저만 받으므로, 패키지도 `npm i -g playwright` 로 설치해 둔다. 사용자가 자기 프로젝트에 `npm i -D playwright` 로 설치했다고 확인해 준 때만 Step 6 에 `--playwright-from-project` 를 준다. 프로젝트에 `node_modules/playwright` 가 있다는 이유만으로는 주지 않는다. 이 옵션이 없으면 프로젝트의 `node_modules` 는 읽지 않는다(저장소가 함께 가져온 코드가 실행되지 않게).
|
|
69
72
|
|
|
@@ -113,7 +116,7 @@ const cost = CLIP_MODE === 'holdFlight'
|
|
|
113
116
|
- 사용자에게 `cost.images` / `cost.videos` / `cost.usd` 와 BUDGET 대비를 보여준다.
|
|
114
117
|
- `cost.videos` 는 **Sora 단가($0.10/초) 기준**이다.
|
|
115
118
|
WAN 단가와 계정별 무료 할당량은 API 로 조회할 수 없다(Model Studio 에 할당량 조회 API 가 문서화돼 있지 않음).
|
|
116
|
-
그러니 "WAN 이 먼저 쓰이고, 실제 WAN 비용은 Model Studio 콘솔에서 확인, 키가
|
|
119
|
+
그러니 "WAN 이 먼저 쓰이고, 실제 WAN 비용은 Model Studio 콘솔에서 확인, 쓸 수 있는 WAN 키가 없으면(소진, 2분 넘는 쿨다운, 시도 한도) 이 Sora 추정이 적용된다" 고 그대로 알린다.
|
|
117
120
|
- `holdFlight` 는 장면 사이 비행 클립만 과금한다(기본 5초 x 장면 수-1). 정지 클립은 스틸을 인코딩해 무료다.
|
|
118
121
|
- WAN 클립 길이는 정수 2~30초(기본 5초), Sora 는 4, 8, 12초뿐이다. 폴백되면 길이가 가장 가까운 Sora 값으로 바뀐다(5초에서 4초).
|
|
119
122
|
- MOBILE=yes 면 세로 체인이 추가돼 대략 2배임을 명시한다.
|
|
@@ -224,19 +227,20 @@ const r = await generateClip({ creds, prompt: flight, size: ORIENTATION, seconds
|
|
|
224
227
|
|
|
225
228
|
- **클립 검토**: `curate-input.json` 을 `"stage": "clips"` 로 다시 쓴다. 테이크마다 클립 파일, 프롬프트, 모델, 길이(`seconds`), 비행이면 `firstFrame`, `lastFrame`, 비용을 적고 같은 검토 페이지로 판정받는다(클립은 무음 반복 재생된다). 재생성은 지적받은 클립만 한다.
|
|
226
229
|
- **키 풀 동작** - WAN 키는 가장 오래전에 쓴 것부터 고른다. 할당량 소진(`AllocationQuota.*`, `Arrearage`, `BudgetLimitExceeded` 등)과 모델 권한 없음(`*AccessDenied`)은 그 키를 24시간 쉬게 하고 다음 키로 다시 제출한다.
|
|
227
|
-
요청 속도 429(`Throttling.RateQuota` 등)는 `Retry-After` 만큼 그 키만 쉬게 할 뿐 퇴출하지 않는다. `Throttling.AllocationQuota` 만 연속 3회면 1시간 쉬게 한다. `InvalidApiKey` 키는 키를 바꿀 때까지 제외한다.
|
|
230
|
+
요청 속도 429(`Throttling.RateQuota` 등)는 `Retry-After` 만큼 그 키만 쉬게 할 뿐 퇴출하지 않는다. `Throttling.AllocationQuota` 만 연속 3회면 1시간 쉬게 한다. `InvalidApiKey` 키는 키를 바꿀 때까지 제외한다. 코드 없는 401 은 403 처럼 24시간(`WAN_EXHAUSTED_TTL_HOURS`) 쉬게 한다. 게이트웨이나 일시 오류의 401 하나로 쓸 수 있는 키를 영구히 빼지 않기 위해서다.
|
|
228
231
|
상태는 `~/.config/banker/3d-intro/video-pool-state.json` 에 지문(엔드포인트, 키, 모델)으로만 남는다.
|
|
229
|
-
- **같은 leg 를 두 번 과금하지 않는다** - 다른 키로 다시 제출하는 것은 첫 제출이
|
|
232
|
+
- **같은 leg 를 두 번 과금하지 않는다** - 다른 키로 다시 제출하는 것은 첫 제출이 과금되지 않았다고 볼 때뿐이다(서버가 거절, 요청을 보내기 전 연결 실패, task 가 키 할당량이나 알려진 일시 오류로 FAILED/CANCELED). FAILED/CANCELED task 가 과금되지 않는다는 것은 전제이고 공식 문서에서 확인하지 못했다. 그 전제가 틀리면 한 leg 가 최대 (키 수 x 4 + 2)번 제출된다.
|
|
230
233
|
- **폴백(chain 모드)** - 쓸 수 있는 WAN 키가 없으면 그 leg 부터 Sora 로 만든다. 체인 도중에 provider 가 바뀌면 화풍이 달라질 수 있으니 leg 마다 `r.provider` 를 기록하고 바뀐 지점을 알린다.
|
|
231
234
|
- **멈추는 경우(재제출, 폴백 안 함)** - 아래 오류에서 같은 leg 를 `generateClip` 으로 다시 부르지 않는다.
|
|
232
235
|
|
|
233
236
|
| 오류 | 뜻 | 다음 행동 |
|
|
234
237
|
|---|---|---|
|
|
235
238
|
| `ContentRejectedError` | 검열(`DataInspectionFailed` 등) | 프롬프트나 프레임을 고쳐 다시 부름 |
|
|
236
|
-
| `kind: 'invalid_request'` | 요청 형식 오류, `ModelNotFound`, 모든 WAN 항목의 형식 오류, Sora 크레덴셜 없이 Sora resume | 설정을 고침(task 는 생기지
|
|
239
|
+
| `kind: 'invalid_request'` | 요청 형식 오류, `ModelNotFound`, 모든 WAN 항목의 형식 오류, Sora 크레덴셜 없이 Sora resume, env 프록시가 키를 막는 http endpoint(`EPROXYKEY`) | 설정을 고침(task 는 생기지 않음. resume 이면 고친 뒤 다시 resume) |
|
|
237
240
|
| `kind: 'timeout'` / `'download'` | task 는 있음(과금됐을 수 있음) | `resumeClip({ creds, provider: err.provider, label: err.label, taskId: err.taskId, seconds: err.seconds })` |
|
|
238
|
-
| `kind: 'submit_unknown'` / `'task_lost'` / `'no_video'` / `'failed'` | 결과를 알 수 없음 | Model Studio 콘솔(또는 Azure)에서 task 를 확인한 뒤 사용자와
|
|
241
|
+
| `kind: 'submit_unknown'` / `'task_lost'` / `'no_video'` / `'failed'` | 결과를 알 수 없음 | Model Studio 콘솔(또는 Azure)에서 task 를 확인한 뒤 사용자와 정함. `task_lost` 인데 콘솔에 task 가 있으면 `resumeClip` 으로 마저 받음(새 제출 없음) |
|
|
239
242
|
| `kind: 'unreachable'` | Sora 연결 거부(아무것도 보내지 않음) | 네트워크를 확인한 뒤 다시 부름 |
|
|
243
|
+
| `kind: 'rate'` | Sora 가 다섯 번 제출 모두 429 로 거절함, 또는 다음 기다림이 `maxRateWaitMs`(기본 120초)보다 김(서버의 `Retry-After`, 없으면 30초부터 두 배로 늘린 값. 만든 job 없음, 과금 없음) | 잠시(`err.retryAfterMs` 가 있으면 그만큼) 기다린 뒤 다시 부름 |
|
|
240
244
|
| `kind` 가 없는 오류 | 예상하지 못한 실패 | 원인을 확인하기 전에는 다시 부르지 않음 |
|
|
241
245
|
|
|
242
246
|
- 클립 해상도는 WAN 과 Sora 가 조금 다를 수 있다. `concatClips` 와 엔진이 크기를 맞춘다.
|
|
@@ -268,6 +272,8 @@ node references/serve.mjs --stop <projectDir>/site # 끝나면 종료
|
|
|
268
272
|
- `intro-fixes.css` 는 항상 붙는다. 엔진의 인라인 transform 이 덮는 패널 세로 가운데 맞춤(`translate`), 860px 이하에서 장면 점과 겹치지 않는 오른쪽 여백과 아래 안내 위로 올린 문구, 높이 500px 이하 가로 화면의 두 단 배치, 어두운 테마에서도 읽히는 주 버튼과 상단 CTA 글자, 고정 헤더를 깨는 `overflow-x: hidden` 대신 `clip` 을 담는다.
|
|
269
273
|
- 기존 사이트에 붙이는 미리보기는 반드시 운영과 같은 CSP 헤더로 서빙한다. 일반 정적 서버에서는 CSP 오류가 보이지 않는다.
|
|
270
274
|
- 상태 파일은 `serve.mjs` 가 서빙 폴더 밖(`<site>.server.json`)에, `curate.mjs` 가 프로젝트 폴더(`curate.server.json`)에 둔다. 검토 서버는 입력에 적힌 테이크와 프레임 가운데 이미지와 영상만, 링크를 따라가도 프로젝트 안의 이미지나 영상일 때만 내준다. 그래서 이 파일과 `.env` 키 파일은 입력에 잘못 적혀도 내려가지 않는다. 읽을 수 없는 파일은 403 으로 답하고 서버는 계속 돈다. 두 서버 모두 Host 가 localhost 나 IP 주소가 아니면 거절한다(DNS 재바인딩 방지). 종료는 `--stop` 으로 한다. 상태 파일의 PID 가 1보다 큰 정수가 아니면 끄지 않는다. 명령줄 패턴으로 `pkill -f` 하지 않는다. 이미 떠 있는 서버를 같은 설정으로 다시 띄우면 그 주소만 알려 준다. CSP, 바인드 주소, 포트가 다르면 `--stop` 으로 먼저 끄라며 멈춘다(exit 1). 검토 페이지의 sha256 은 파일을 나눠 읽어 크기 제한이 없고, 서버를 띄울 때 미리 계산한다.
|
|
275
|
+
- 상태 파일의 PID 가 1보다 큰 정수가 아니거나 기록된 주소가 이 기기가 아니면 그 서버를 끄지 않는다(`--stop` 은 종료 1, 파일은 사람이 보도록 남긴다). 상태 파일은 남의 저장소 안에 있을 수 있기 때문이다.
|
|
276
|
+
- 검토 페이지는 테이크의 sha256 을 5초까지 기다린다. 그 안에 읽기가 끝나지 않은 테이크는 sha256 자리에 `읽는 중(새로 고치면 보임)` 이 보이고, 다음 화면에 그 값이 나온다. 방금 바뀐 파일(3초 안)은 화면마다 다시 읽는다.
|
|
271
277
|
- 휴대폰 실기기로 볼 때만 `PREVIEW_HOST=0.0.0.0` 을 쓴다. 같은 네트워크에 미공개 산출물이 보인다는 경고가 나온다.
|
|
272
278
|
- 프로젝트 관례상 **claude.ai 아티팩트를 만들지 않는다** - 로컬 페이지를 포트로 서빙해 사용자가 브라우저로 확인한다.
|
|
273
279
|
- 사용자 검토를 받는다. 지적이 있으면 카피, 매니페스트, 해당 클립만 고치고 다시 조립한다.
|