sprag-cli 3.78.0 → 3.79.1
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/README.ko.md +34 -3
- package/README.md +34 -3
- package/docs/TEAM.ko.md +1 -1
- package/docs/TEAM.md +1 -1
- package/package.json +1 -1
- package/src/commands/team.js +5 -3
- package/src/team-sync.js +3 -0
package/README.ko.md
CHANGED
|
@@ -258,13 +258,44 @@ sprag feedback "Bedrock에서 5m TTL 칩이 사라지지 않아요"
|
|
|
258
258
|
|
|
259
259
|
## 팀
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
CLI는 무료이고 컴퓨터 한 대에서 혼자 동작합니다. 조직에는 **Sprag Pro** 와 **Sprag Enterprise** 가 같은 로컬 세션 로그로 만든 공용 대시보드를 더해 줍니다. 도입은 [sales@sprag.io](mailto:sales@sprag.io)로 문의해 주세요.
|
|
262
|
+
|
|
263
|
+
### Pro: 팀 대시보드
|
|
264
|
+
|
|
265
|
+
<a href="https://sprag.io/assets/video/plan-pro-ko.mp4"><img src="https://raw.githubusercontent.com/rootstudioyaml/sprag/main/docs/plan-pro-ko.gif" width="640" alt="팀원마다 동물 캐릭터로 앉아 있는 가상 사무실, 지출과 절감액, 좌석, 30일 차트가 있는 조직 대시보드, 한 번 승인하면 모든 컴퓨터에 적용되는 팀 규칙을 차례로 보여 줍니다."></a>
|
|
266
|
+
|
|
267
|
+
- 조직 대시보드와 30일 추이 차트
|
|
268
|
+
- 사람마다 동물 캐릭터가 앉아 있는 가상 사무실
|
|
269
|
+
- 컴퓨터별 상태가 보이는 좌석 명단
|
|
270
|
+
- 세션 시작 때 적용되는 팀 승인 규칙
|
|
271
|
+
- `sprag team join` 으로 조직 배포
|
|
272
|
+
- 오너와 어드민 역할, 활동 기록
|
|
273
|
+
|
|
274
|
+
### Enterprise: 프롬프트 모니터링
|
|
275
|
+
|
|
276
|
+
<a href="https://sprag.io/assets/video/plan-ent-ko.mp4"><img src="https://raw.githubusercontent.com/rootstudioyaml/sprag/main/docs/plan-ent-ko.gif" width="640" alt="사용자별 프롬프트 사용량과 30일 추이, 한 사람의 프롬프트 검색, 팀별로 프롬프트 수집을 켜는 설정을 보여 줍니다."></a>
|
|
277
|
+
|
|
278
|
+
Pro 의 기능에 더해 다음을 제공합니다.
|
|
279
|
+
|
|
280
|
+
- 팀별 프롬프트 수집, 비밀 값은 가림
|
|
281
|
+
- 정책을 켜기 전 기록은 수집하지 않음
|
|
282
|
+
- 사용자별 프롬프트 사용량과 30일 추이
|
|
283
|
+
- 사용자별 프롬프트 목록과 검색
|
|
284
|
+
- 모든 멤버에게 보이는 수집 정책
|
|
285
|
+
|
|
286
|
+
프롬프트 수집은 조직 오너나 어드민이 켜기 전까지 꺼져 있습니다.
|
|
287
|
+
|
|
288
|
+
<sub>두 영상 모두 데모 대시보드에서 예시 데이터로 녹화했습니다. 전체 영상: <a href="https://sprag.io/assets/video/plan-pro-ko.mp4">Pro (30초)</a> · <a href="https://sprag.io/assets/video/plan-ent-ko.mp4">Enterprise (30초)</a></sub>
|
|
289
|
+
|
|
290
|
+
### 컴퓨터가 보내는 것
|
|
291
|
+
|
|
292
|
+
Sprag 은 켜지 않으면 로컬에서만 동작합니다. `sprag team join <토큰>` 을 실행하거나(조직 전체는 `SPRAG_TEAM_TOKEN`) 하면 컴퓨터마다 하루에 한 행씩 올라갑니다. 내용은 지출, 절감액, 위임 실행 횟수, 모델 계열 비중입니다. 대화 기록, 파일 경로, 프로젝트 이름은 보내지 않습니다. 프롬프트도 Enterprise 조직이 수집 정책을 켜지 않는 한 보내지 않으며, `sprag team status --show-payload` 로 올라갈 내용을 그대로 볼 수 있습니다. 그 대신 팀 소유자는 대시보드에서 구성원별 합계를 보고, 모든 구성원에게 자동으로 적용될 래칫 룰을 승인할 수 있습니다.
|
|
262
293
|
|
|
263
294
|
`SPRAG_NO_TEAM_SYNC=1` 은 팀 관련 통신을 모두 끄고, `sprag team leave` 는 참여를 해제합니다.
|
|
264
295
|
|
|
265
296
|
- [팀 기능 안내](docs/TEAM.ko.md)
|
|
266
|
-
-
|
|
267
|
-
-
|
|
297
|
+
- 오너와 어드민용 팀 콘솔: https://sprag.io/team/
|
|
298
|
+
- 플랜 안내: https://sprag.io/license/
|
|
268
299
|
|
|
269
300
|
## 라이선스
|
|
270
301
|
|
package/README.md
CHANGED
|
@@ -312,13 +312,44 @@ For a bug, please include the tool version (`sprag --version`) and your OS. For
|
|
|
312
312
|
|
|
313
313
|
## Teams
|
|
314
314
|
|
|
315
|
-
|
|
315
|
+
The CLI is free and works on its own on one machine. For organizations, **Sprag Pro** and **Sprag Enterprise** add a shared dashboard built from the same local session logs. To start, write to [sales@sprag.io](mailto:sales@sprag.io).
|
|
316
|
+
|
|
317
|
+
### Pro: team dashboard
|
|
318
|
+
|
|
319
|
+
<a href="https://sprag.io/assets/video/plan-pro-en.mp4"><img src="https://raw.githubusercontent.com/rootstudioyaml/sprag/main/docs/plan-pro-en.gif" width="640" alt="A virtual office where every teammate sits as an animal character, then the organization dashboard with spend, savings, seats and a 30-day chart, then team rules approved once and picked up by every machine."></a>
|
|
320
|
+
|
|
321
|
+
- Organization dashboard with a 30-day chart
|
|
322
|
+
- A virtual office with an animal for each person
|
|
323
|
+
- Seat roster with each machine's status
|
|
324
|
+
- Team-approved rules applied at session start
|
|
325
|
+
- Rollout with `sprag team join`
|
|
326
|
+
- Owner and admin roles, activity log
|
|
327
|
+
|
|
328
|
+
### Enterprise: prompt monitoring
|
|
329
|
+
|
|
330
|
+
<a href="https://sprag.io/assets/video/plan-ent-en.mp4"><img src="https://raw.githubusercontent.com/rootstudioyaml/sprag/main/docs/plan-ent-en.gif" width="640" alt="Per-user prompt usage with a 30-day trend, a prompt search for one person, and the team setting that turns prompt capture on."></a>
|
|
331
|
+
|
|
332
|
+
Everything in Pro, plus:
|
|
333
|
+
|
|
334
|
+
- Prompt capture per team, with secrets redacted
|
|
335
|
+
- Nothing from before the policy was turned on
|
|
336
|
+
- Per-user prompt usage and a 30-day trend
|
|
337
|
+
- Each user's prompt list with search
|
|
338
|
+
- A capture policy every member can see
|
|
339
|
+
|
|
340
|
+
Prompt capture is off unless an organization owner or admin turns it on.
|
|
341
|
+
|
|
342
|
+
<sub>Both videos are recorded from the demo dashboard with sample data. Full videos: <a href="https://sprag.io/assets/video/plan-pro-en.mp4">Pro (30s)</a> · <a href="https://sprag.io/assets/video/plan-ent-en.mp4">Enterprise (30s)</a></sub>
|
|
343
|
+
|
|
344
|
+
### What a machine sends
|
|
345
|
+
|
|
346
|
+
Sprag stays local unless you opt in. With `sprag team join <token>` (or `SPRAG_TEAM_TOKEN` for a whole organization), each machine uploads one row per day: spend, savings, delegated-run count and model-family share. Transcripts, file paths and project names are never sent. Prompts are not sent either, unless an Enterprise organization turns on prompt capture, and `sprag team status --show-payload` prints exactly what would go up. In return the team owner sees per-member totals in a dashboard and can approve ratchet rules that every member picks up automatically.
|
|
316
347
|
|
|
317
348
|
`SPRAG_NO_TEAM_SYNC=1` turns all team traffic off, and `sprag team leave` removes the membership.
|
|
318
349
|
|
|
319
350
|
- [Team layer guide](docs/TEAM.md)
|
|
320
|
-
-
|
|
321
|
-
- Plans
|
|
351
|
+
- Team console for owners and admins: https://sprag.io/team/
|
|
352
|
+
- Plans: https://sprag.io/license/
|
|
322
353
|
|
|
323
354
|
## License
|
|
324
355
|
|
package/docs/TEAM.ko.md
CHANGED
|
@@ -117,7 +117,7 @@ Sprag 은 룰을 `~/.claude/ratchet-team.md`(Codex 는 `<CODEX_HOME>/ratchet-tea
|
|
|
117
117
|
|
|
118
118
|
## 대시보드
|
|
119
119
|
|
|
120
|
-
https://sprag.io/team/ 에서 등록된 오너나 어드민이 이메일 코드로 로그인하고, 팀을 만들고, 초대 토큰을 받습니다.
|
|
120
|
+
https://sprag.io/team/ 에서 등록된 오너나 어드민이 이메일 코드로 로그인하고, 팀을 만들고, 초대 토큰을 받습니다. 새 조직은 sales@sprag.io 로 문의합니다. 오너, 어드민, 초대 대기 중 어느 쪽에도 없는 이메일은 코드를 보내기 전에 거절하며, 조직 오너에게 추가를 요청하라고 안내합니다. 초대받은 사람은 처음 로그인할 때 자동으로 오너나 어드민이 됩니다. 여기서 구성원별 지출과 절감액을 보고, 규칙 탭에서 조직 룰과 팀 룰을 관리하고, 구성원을 내보낼 수 있습니다. 조직 패널에는 요금제, 한도 대비 사용 좌석, 어드민, 전체 팀이 보입니다. 슈퍼유저는 sprag.io/ops/ 에서 모든 조직을 봅니다.
|
|
121
121
|
|
|
122
122
|
대시보드 맨 위의 기간 선택(7일, 30일, 90일, 이번 달, 지난 달, 직접 선택)이 멤버 표, 사용량 차트, 프롬프트 사용량 탭의 기간을 정합니다. 기본값은 최근 30일이고, 내 컴퓨터의 달력 날짜를 쓰며 종료일도 포함합니다. 최대 365일까지 고를 수 있습니다. 고른 기간은 주소(`?from=2026-10-01&to=2026-10-18`)에 남으므로 새로고침하거나 링크를 공유해도 같은 기간이 보입니다. sprag.io/ops/ 슈퍼유저 콘솔에도 같은 선택이 있어 조직 표, 조직 머리말, 조직의 프롬프트 사용량에 적용됩니다.
|
|
123
123
|
|
package/docs/TEAM.md
CHANGED
|
@@ -118,7 +118,7 @@ Create a team inside an organization you administer from the CLI with `sprag tea
|
|
|
118
118
|
|
|
119
119
|
## The dashboard
|
|
120
120
|
|
|
121
|
-
https://sprag.io/team/ is where a registered owner or admin signs in with an email code, creates a team and gets the invite token.
|
|
121
|
+
https://sprag.io/team/ is where a registered owner or admin signs in with an email code, creates a team and gets the invite token. A new organization starts by writing to sales@sprag.io. An email that is not an owner, an admin or a pending invite is refused before any code is sent, with a message to ask the organization's owner to add it. Invited people become owner or admin automatically on their first sign-in. From there they see per-member spend and savings, manage organization and team rules on the Rules tab, and remove members. The organization panel shows the plan, seats used against the limit, admins and every team. The superuser sees every organization at sprag.io/ops/.
|
|
122
122
|
|
|
123
123
|
A date range control at the top of the dashboard (7d, 30d, 90d, This month, Last month or Custom) sets the period for the members table, the Usage chart and the prompt usage tab. It defaults to the last 30 days, uses your local calendar days with the end date included, and allows 365 days at most. The choice is kept in the page address (`?from=2026-10-01&to=2026-10-18`), so a reload or a shared link shows the same period. The superuser console at /ops/ has the same control for the organization table, the organization header and its prompt usage.
|
|
124
124
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprag-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.79.1",
|
|
4
4
|
"description": "Model-delegation router for Claude Code and Codex: lookups, checks and test runs go to cheaper models, documents go in as compact Markdown, and a live statusline shows spend and savings.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/team.js
CHANGED
|
@@ -15,7 +15,7 @@ import { pendingPrompts } from '../team-prompts.js';
|
|
|
15
15
|
import { memberId } from '../member-id.js';
|
|
16
16
|
import {
|
|
17
17
|
loadTeamState, deviceInfo, isJoined, joinTeam, leaveTeam, syncTeam, autoJoin, aggregateDaily, rpc,
|
|
18
|
-
teamRulesCachePath, teamSyncDisabled, requestSignInCode, verifySignInCode, createTeam, isSeatLimitError,
|
|
18
|
+
teamRulesCachePath, teamSyncDisabled, requestSignInCode, verifySignInCode, createTeam, isSeatLimitError, isOrgExpiredError,
|
|
19
19
|
} from '../team-sync.js';
|
|
20
20
|
|
|
21
21
|
const T = {
|
|
@@ -40,6 +40,7 @@ const T = {
|
|
|
40
40
|
aborted: 'Not joined.',
|
|
41
41
|
joined: (n) => `Joined team "${n}". Check it with: sprag team status`,
|
|
42
42
|
seatLimit: 'This organization has no free seat. Ask your organization owner or admin to add seats, then join again.',
|
|
43
|
+
orgExpired: "This organization's paid term has ended, so the server no longer accepts uploads or joins. Ask your organization owner to renew it (sales@sprag.io).",
|
|
43
44
|
org: 'Organization',
|
|
44
45
|
seats: (u, l) => `${u}/${l} seats used`,
|
|
45
46
|
orgCreated: (n, u, l) => `Organization: ${n}${u != null && l != null ? ` (${u}/${l} seats used)` : ''}`,
|
|
@@ -105,6 +106,7 @@ const T = {
|
|
|
105
106
|
aborted: '참여하지 않았습니다.',
|
|
106
107
|
joined: (n) => `팀 "${n}" 에 참여했습니다. 확인: sprag team status`,
|
|
107
108
|
seatLimit: '이 조직에 남은 좌석이 없습니다. 조직 오너나 어드민에게 좌석 추가를 요청한 뒤 다시 참여하세요',
|
|
109
|
+
orgExpired: '조직의 이용 기간이 끝나 서버가 업로드와 참여를 받지 않습니다. 조직 오너에게 연장을 요청하세요(sales@sprag.io)',
|
|
108
110
|
org: '조직',
|
|
109
111
|
seats: (u, l) => `좌석 ${u}/${l} 사용 중`,
|
|
110
112
|
orgCreated: (n, u, l) => `조직: ${n}${u != null && l != null ? ` (좌석 ${u}/${l} 사용 중)` : ''}`,
|
|
@@ -284,7 +286,7 @@ export async function run({ args, hasFlag, getArg, version, fetch, interactive,
|
|
|
284
286
|
}
|
|
285
287
|
out(`${m.name}: ${st.displayName}`);
|
|
286
288
|
out(st.lastSyncAt ? m.lastSync(new Date(st.lastSyncAt).toLocaleString(), st.lastSyncRows || 0) : m.neverSynced);
|
|
287
|
-
if (st.lastError) out(`${m.lastError}: ${st.lastError}`);
|
|
289
|
+
if (st.lastError) out(isOrgExpiredError(st.lastError) ? m.orgExpired : `${m.lastError}: ${st.lastError}`);
|
|
288
290
|
if (hasFlag('--show-payload')) {
|
|
289
291
|
out(`device: ${JSON.stringify(st.deviceInfo || deviceInfo())}`);
|
|
290
292
|
out(JSON.stringify(await aggregateDaily(), null, 2));
|
|
@@ -336,7 +338,7 @@ export async function run({ args, hasFlag, getArg, version, fetch, interactive,
|
|
|
336
338
|
return verb && verb !== 'help' ? process.exit(2) : undefined;
|
|
337
339
|
}
|
|
338
340
|
} catch (e) {
|
|
339
|
-
console.error(isSeatLimitError(e) ? m.seatLimit : e.message);
|
|
341
|
+
console.error(isSeatLimitError(e) ? m.seatLimit : isOrgExpiredError(e) ? m.orgExpired : e.message);
|
|
340
342
|
return process.exit(1);
|
|
341
343
|
}
|
|
342
344
|
}
|
package/src/team-sync.js
CHANGED
|
@@ -247,6 +247,9 @@ export class SeatLimitError extends Error {
|
|
|
247
247
|
|
|
248
248
|
export const isSeatLimitError = (e) => !!e && (e.code === 'SEAT_LIMIT' || /seat limit reached/i.test(String(e.message || '')));
|
|
249
249
|
|
|
250
|
+
/** The server refuses uploads and joins 14 days after an organization's paid term ends ('org_expired: ...'). */
|
|
251
|
+
export const isOrgExpiredError = (e) => /\borg_expired\b/.test(String((e && e.message) || e || ''));
|
|
252
|
+
|
|
250
253
|
/** Local calendar day, same key as stats.js. */
|
|
251
254
|
function dayKey(ms) {
|
|
252
255
|
const d = new Date(ms);
|