democut 1.0.76 → 1.0.78

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.
Files changed (2) hide show
  1. package/dist/cli.js +212 -7
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6916,7 +6916,7 @@ import { realpathSync } from "fs";
6916
6916
  import { fileURLToPath } from "url";
6917
6917
 
6918
6918
  // src/version.ts
6919
- var VERSION = "1.0.76";
6919
+ var VERSION = "1.0.78";
6920
6920
 
6921
6921
  // src/device-flow.ts
6922
6922
  var DeviceFlowError = class extends Error {
@@ -9144,7 +9144,7 @@ var GENERATED_TOOLS = [
9144
9144
  },
9145
9145
  {
9146
9146
  "name": "democut_credit_ledger",
9147
- "description": "\uD06C\uB808\uB527 \uC0AC\uC6A9 \uB0B4\uC5ED(\uCD5C\uC2E0\uC21C, keyset). \u300C\uC65C \uC794\uC561\uC774 \uC774\uB9CC\uD07C \uC904\uC5C8\uB098\u300D \uB97C \uB2F5\uD560 \uB54C \uC4F4\uB2E4 \u2014 \uD589\uB9C8\uB2E4 \uBB34\uC5C7\uC5D0\xB7\uC5B8\uC81C\xB7\uC5BC\uB9C8\uC778\uC9C0\uAC00 \uC788\uB2E4.",
9147
+ "description": "\uD06C\uB808\uB527 \uC0AC\uC6A9 \uB0B4\uC5ED(\uCD5C\uC2E0\uC21C, keyset). \u300C\uC65C \uC794\uC561\uC774 \uC774\uB9CC\uD07C \uC904\uC5C8\uB098\u300D \uB97C \uB2F5\uD560 \uB54C \uC4F4\uB2E4 \u2014 \uD589\uB9C8\uB2E4 \uBB34\uC5C7\uC5D0\xB7\uC5B8\uC81C\xB7\uC5BC\uB9C8\uC778\uC9C0\uAC00 \uC788\uB2E4. project(slug)\xB7category(democut_credit_summary \uC758 categories[].key)\uB85C \uAC70\uB97C \uC218 \uC788\uB2E4.",
9148
9148
  "inputSchema": {
9149
9149
  "type": "object",
9150
9150
  "properties": {
@@ -9164,6 +9164,41 @@ var GENERATED_TOOLS = [
9164
9164
  "maximum": 200,
9165
9165
  "minimum": 1,
9166
9166
  "type": "integer"
9167
+ },
9168
+ "project": {
9169
+ "anyOf": [
9170
+ {
9171
+ "type": "string"
9172
+ },
9173
+ {
9174
+ "type": "null"
9175
+ }
9176
+ ],
9177
+ "default": null,
9178
+ "description": "\uC774 \uD504\uB85C\uC81D\uD2B8(slug)\uC758 \uD589\uB9CC"
9179
+ },
9180
+ "category": {
9181
+ "anyOf": [
9182
+ {
9183
+ "enum": [
9184
+ "ai_video",
9185
+ "ai_image",
9186
+ "avatar",
9187
+ "voice",
9188
+ "subtitle",
9189
+ "motion",
9190
+ "agent",
9191
+ "publish",
9192
+ "other"
9193
+ ],
9194
+ "type": "string"
9195
+ },
9196
+ {
9197
+ "type": "null"
9198
+ }
9199
+ ],
9200
+ "default": null,
9201
+ "description": "\uC774 \uC0AC\uC6A9 \uD56D\uBAA9 \uBB36\uC74C\uC758 \uD589\uB9CC(democut_credit_summary \uC758 categories[].key)"
9167
9202
  }
9168
9203
  },
9169
9204
  "required": [],
@@ -9191,6 +9226,110 @@ var GENERATED_TOOLS = [
9191
9226
  "openWorldHint": false
9192
9227
  }
9193
9228
  },
9229
+ {
9230
+ "name": "democut_credit_summary",
9231
+ "description": "\uD06C\uB808\uB527 \uC0AC\uC6A9 \uD1B5\uACC4(0\uC6D0, \uBD80\uC791\uC6A9 \uC5C6\uC74C). \u300C\uC774\uBC88 \uB2EC \uC5BC\uB9C8 \uC37C\uB098\xB7\uBB34\uC5C7\uC5D0\xB7\uC5B4\uB290 \uD504\uB85C\uC81D\uD2B8\uC5D0\xB7\uC5B8\uC81C \uBC14\uB2E5\uB098\uB098\u300D \uB97C \uB2F5\uD560 \uB54C \uC4F4\uB2E4 \u2014 \uC21C\uC0AC\uC6A9\uC561(\uC0AC\uC6A9 \u2212 \uD658\uBD88), \uBE44\uAD50 \uAE30\uAC04, \uCD5C\uADFC 14\uC77C \uD3C9\uADE0\uACFC \uC18C\uC9C4 \uC608\uC0C1 \uC77C\uC218, \uC77C\uBCC4\xB7\uD56D\uBAA9\uBCC4\xB7\uD504\uB85C\uC81D\uD2B8\uBCC4 \uD569\uACC4. range: current(\uC774\uBC88 \uB2EC, \uAE30\uBCF8)\xB7previous(\uC9C0\uB09C\uB2EC)\xB730d. \uB0A0\uC9DC\uB294 \uD55C\uAD6D \uC2DC\uAC04\uC774\uB2E4. \uB204\uAC00 \uC37C\uB294\uC9C0\uB294 \uB2F5\uD558\uC9C0 \uBABB\uD55C\uB2E4.",
9232
+ "inputSchema": {
9233
+ "type": "object",
9234
+ "properties": {
9235
+ "range": {
9236
+ "default": "current",
9237
+ "description": "current = \uC774\uBC88 \uB2EC 1\uC77C\uBD80\uD130 \uC624\uB298, previous = \uC9C0\uB09C\uB2EC \uC804\uCCB4, 30d = \uC624\uB298\uAE4C\uC9C0 30\uC77C(\uB0A0\uC9DC\uB294 \uD55C\uAD6D \uC2DC\uAC04)",
9238
+ "enum": [
9239
+ "current",
9240
+ "previous",
9241
+ "30d"
9242
+ ],
9243
+ "type": "string"
9244
+ }
9245
+ },
9246
+ "required": [],
9247
+ "additionalProperties": false
9248
+ },
9249
+ "outputSchema": {
9250
+ "type": "object",
9251
+ "properties": {
9252
+ "enabled": {
9253
+ "type": "boolean"
9254
+ },
9255
+ "range": {
9256
+ "type": "string"
9257
+ },
9258
+ "start_date": {
9259
+ "type": "string"
9260
+ },
9261
+ "end_date": {
9262
+ "type": "string"
9263
+ },
9264
+ "net_spent_krw": {
9265
+ "type": "integer"
9266
+ },
9267
+ "spent_krw": {
9268
+ "type": "integer"
9269
+ },
9270
+ "refunded_krw": {
9271
+ "type": "integer"
9272
+ },
9273
+ "granted_krw": {
9274
+ "type": "integer"
9275
+ },
9276
+ "compare_start_date": {
9277
+ "type": "string"
9278
+ },
9279
+ "compare_end_date": {
9280
+ "type": "string"
9281
+ },
9282
+ "compare_net_spent_krw": {
9283
+ "type": "integer"
9284
+ },
9285
+ "balance_krw": {
9286
+ "type": "integer"
9287
+ },
9288
+ "avg_daily_krw": {
9289
+ "type": "integer"
9290
+ },
9291
+ "runway_days": {},
9292
+ "daily": {
9293
+ "type": "array"
9294
+ },
9295
+ "categories": {
9296
+ "type": "array"
9297
+ },
9298
+ "projects": {
9299
+ "type": "array"
9300
+ },
9301
+ "projects_other_krw": {
9302
+ "type": "integer"
9303
+ },
9304
+ "unassigned_krw": {
9305
+ "type": "integer"
9306
+ }
9307
+ },
9308
+ "required": [
9309
+ "range",
9310
+ "start_date",
9311
+ "end_date",
9312
+ "net_spent_krw",
9313
+ "spent_krw",
9314
+ "refunded_krw",
9315
+ "granted_krw",
9316
+ "compare_start_date",
9317
+ "compare_end_date",
9318
+ "compare_net_spent_krw",
9319
+ "balance_krw",
9320
+ "avg_daily_krw",
9321
+ "daily",
9322
+ "categories",
9323
+ "projects"
9324
+ ]
9325
+ },
9326
+ "annotations": {
9327
+ "readOnlyHint": true,
9328
+ "destructiveHint": false,
9329
+ "idempotentHint": true,
9330
+ "openWorldHint": false
9331
+ }
9332
+ },
9194
9333
  {
9195
9334
  "name": "democut_list_characters",
9196
9335
  "description": "\uC544\uBC14\uD0C0 \uBAA9\uB85D.",
@@ -12597,6 +12736,12 @@ var TOOL_META = {
12597
12736
  "method": "GET",
12598
12737
  "path": "/api/workspaces/{workspace_id}/credits/ledger"
12599
12738
  },
12739
+ "democut_credit_summary": {
12740
+ "cost": "none",
12741
+ "group": "credits",
12742
+ "method": "GET",
12743
+ "path": "/api/workspaces/{workspace_id}/credits/summary"
12744
+ },
12600
12745
  "democut_list_characters": {
12601
12746
  "cost": "none",
12602
12747
  "group": "character",
@@ -12938,7 +13083,16 @@ function classifyApiError(e, ctx) {
12938
13083
  );
12939
13084
  }
12940
13085
  return {
12941
- safety: e.status >= 500 && ctx.submitted ? "unsafe" : e.retriable === false ? "fixable" : "safe",
13086
+ // ★★ **재과금 안전성과 재시도 유효성은 다른 축이다**(GitLab #43). 서버의 `retry_safe` 는
13087
+ // 「다시 보내도 **두 번 청구되지 않는다**」 는 뜻이지 「그대로 다시 하면 **된다**」 가 아니다.
13088
+ // 그 둘을 섞어 쓰던 동안 없는 프로젝트(404·`retry_safe=True`)가 TRANSIENT(3)로 나갔고,
13089
+ // 에이전트는 같은 슬러그로 재시도해 같은 404 를 다시 받았다. 슬러그를 고쳐야 하는 오류다.
13090
+ // 그래서 **상태로 가른다** — 4xx 는 요청 문제라 FIXABLE, 5xx 만 TRANSIENT 다.
13091
+ // (`api-client.ts` 도 `retriable` 을 「사람에게 보여줄 정보이지 자동 행동의 근거가 아니다」
13092
+ // 라고 적어 둔다. 과금 축은 아래 `notCharged` 가 그대로 든다.)
13093
+ // ⚠️ 429·408 이 생기면 그때는 「기다렸다 그대로」 가 맞으므로 여기 예외를 더한다 —
13094
+ // 지금 계약(`contracts/error_codes.py`)에는 둘 다 없다.
13095
+ safety: e.status >= 500 ? ctx.submitted ? "unsafe" : "safe" : "fixable",
12942
13096
  notCharged: e.status < 500,
12943
13097
  lines
12944
13098
  };
@@ -13295,6 +13449,8 @@ function ledger(baseUrl, workspaceId, opts = {}, deps = {}) {
13295
13449
  const q = new URLSearchParams();
13296
13450
  q.set("limit", String(opts.limit ?? LEDGER_DEFAULT_LIMIT));
13297
13451
  if (opts.cursor !== void 0) q.set("cursor", opts.cursor);
13452
+ if (opts.project) q.set("project", opts.project);
13453
+ if (opts.category) q.set("category", opts.category);
13298
13454
  return apiRequest(
13299
13455
  baseUrl,
13300
13456
  `/api/workspaces/${encodeURIComponent(workspaceId)}/credits/ledger?${q}`,
@@ -13302,6 +13458,14 @@ function ledger(baseUrl, workspaceId, opts = {}, deps = {}) {
13302
13458
  deps
13303
13459
  );
13304
13460
  }
13461
+ function summary(baseUrl, workspaceId, range, deps = {}) {
13462
+ return apiRequest(
13463
+ baseUrl,
13464
+ `/api/workspaces/${encodeURIComponent(workspaceId)}/credits/summary?range=${range}`,
13465
+ {},
13466
+ deps
13467
+ );
13468
+ }
13305
13469
 
13306
13470
  // src/projects.ts
13307
13471
  var PROJECTS_DEFAULT_LIMIT = 30;
@@ -13486,7 +13650,12 @@ function creditLedger(a = {}, deps = {}) {
13486
13650
  const out4 = await ledger(
13487
13651
  base,
13488
13652
  ws,
13489
- { limit, ...pageNum !== void 0 ? { cursor: String(pageNum) } : {} },
13653
+ {
13654
+ limit,
13655
+ ...pageNum !== void 0 ? { cursor: String(pageNum) } : {},
13656
+ ...typeof a.project === "string" && a.project ? { project: a.project } : {},
13657
+ ...typeof a.category === "string" && a.category ? { category: a.category } : {}
13658
+ },
13490
13659
  deps
13491
13660
  );
13492
13661
  if (out4.entries.length === 0) {
@@ -13500,8 +13669,8 @@ function creditLedger(a = {}, deps = {}) {
13500
13669
  const when = (e.created_at ?? "").slice(0, 16).replace("T", " ");
13501
13670
  const parts = [e.display_name];
13502
13671
  if (e.units_label) parts.push(e.units_label);
13503
- if (e.project_slug) parts.push(e.project_slug);
13504
- if (e.reason) parts.push(e.reason);
13672
+ if (e.project_slug) parts.push(e.project_title ? `${e.project_title} (${e.project_slug})` : e.project_slug);
13673
+ if (e.reason_label || e.reason) parts.push(e.reason_label || e.reason);
13505
13674
  const sign = e.amount_krw > 0 ? "+" : "";
13506
13675
  lines.push(
13507
13676
  `${when} \xB7 ${parts.join(" \xB7 ")} \xB7 ${sign}${e.amount_krw.toLocaleString("ko-KR")}\uC6D0 (\uC794\uC561 ${e.balance_after_krw.toLocaleString("ko-KR")}\uC6D0)`
@@ -13514,6 +13683,38 @@ function creditLedger(a = {}, deps = {}) {
13514
13683
  return { text: lines.join("\n"), structured: callableStructured(out4) };
13515
13684
  });
13516
13685
  }
13686
+ var SUMMARY_RANGES = ["current", "previous", "30d"];
13687
+ var RANGE_LABEL = {
13688
+ current: "\uC774\uBC88 \uB2EC",
13689
+ previous: "\uC9C0\uB09C\uB2EC",
13690
+ "30d": "\uCD5C\uADFC 30\uC77C"
13691
+ };
13692
+ function creditSummary(a = {}, deps = {}) {
13693
+ return guarded(READ_ONLY, async () => {
13694
+ const range = a.range ?? "current";
13695
+ if (!SUMMARY_RANGES.includes(range)) {
13696
+ return { isError: true, text: `range \uB294 ${SUMMARY_RANGES.join(", ")} \uC911 \uD558\uB098\uC785\uB2C8\uB2E4: ${JSON.stringify(range)}` };
13697
+ }
13698
+ const r = range;
13699
+ const base = resolveBaseUrl(deps.baseUrl);
13700
+ const ws = await resolveWorkspace(base, deps);
13701
+ if (!ws) return NO_WORKSPACE;
13702
+ const out4 = await summary(base, ws, r, deps);
13703
+ const lines = [
13704
+ `${RANGE_LABEL[r]}(${out4.start_date} ~ ${out4.end_date}) \uC21C\uC0AC\uC6A9 ${krw(out4.net_spent_krw)} (\uC0AC\uC6A9 ${krw(out4.spent_krw)} \xB7 \uD658\uBD88 ${krw(out4.refunded_krw)})`,
13705
+ `\uBE44\uAD50 \uAE30\uAC04(${out4.compare_start_date} ~ ${out4.compare_end_date}) ${krw(out4.compare_net_spent_krw)}`,
13706
+ `\uC794\uC561 ${krw(out4.balance_krw)} \xB7 \uCD5C\uADFC 14\uC77C \uD558\uB8E8 \uD3C9\uADE0 ${krw(out4.avg_daily_krw)}` + (out4.runway_days != null ? ` \xB7 \uC774 \uC18D\uB3C4\uBA74 \uC57D ${out4.runway_days}\uC77C \uB4A4 \uBC14\uB2E5` : "")
13707
+ ];
13708
+ if (out4.categories.length) {
13709
+ lines.push("", "\uD56D\uBAA9\uBCC4: " + out4.categories.map((c) => `${c.label} ${krw(c.net_spent_krw)}`).join(" \xB7 "));
13710
+ }
13711
+ if (out4.projects.length) {
13712
+ lines.push("\uD504\uB85C\uC81D\uD2B8\uBCC4(\uC0C1\uC704): " + out4.projects.map((p) => `${p.title ?? p.slug} ${krw(p.net_spent_krw)}`).join(" \xB7 "));
13713
+ }
13714
+ lines.push("", "\uD589 \uB2E8\uC704\uB85C \uBCF4\uB824\uBA74 credit_ledger \uC5D0 project\xB7category \uB85C \uAC70\uB974\uC138\uC694.");
13715
+ return { text: lines.join("\n"), structured: callableStructured(out4) };
13716
+ });
13717
+ }
13517
13718
  function projectLine(p) {
13518
13719
  const parts = [p.slug, p.title || "(\uC81C\uBAA9 \uC5C6\uC74C)", `\uCEF7 ${p.cut_count ?? 0}\uAC1C`];
13519
13720
  const updated = (p.updated_at ?? "").slice(0, 10);
@@ -15475,6 +15676,8 @@ function dispatch(name, args, deps = {}) {
15475
15676
  return creditBalance(deps);
15476
15677
  case "democut_credit_ledger":
15477
15678
  return creditLedger(args, deps);
15679
+ case "democut_credit_summary":
15680
+ return creditSummary(args, deps);
15478
15681
  case "democut_list_projects":
15479
15682
  return listProjects(args, deps);
15480
15683
  case "democut_get_project":
@@ -15839,8 +16042,10 @@ function exitForSafety(safety) {
15839
16042
  return EXIT.TRANSIENT;
15840
16043
  case "unsafe":
15841
16044
  return EXIT.UPSTREAM_REJECTED;
15842
- default:
16045
+ case "unknown":
15843
16046
  return EXIT.GENERAL;
16047
+ default:
16048
+ return EXIT.FIXABLE;
15844
16049
  }
15845
16050
  }
15846
16051
  function emit(result, json) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "democut",
3
- "version": "1.0.76",
3
+ "version": "1.0.78",
4
4
  "description": "DemoCut 에이전트 CLI — device flow 로그인(RFC 8628) + 영상 생성",
5
5
  "license": "MIT",
6
6
  "author": "InfoGrab",