@bstage-sdk/cli 0.8.3 → 0.8.5

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/dist/MIGRATION.md CHANGED
@@ -51,6 +51,63 @@
51
51
 
52
52
  ---
53
53
 
54
+ ## → cli 0.8.5 · ai-toolkit 0.8.5
55
+
56
+ ### `bstage doctor`: 포털 진단이 실패해도 종료 코드 1 — `자동` · `선택`
57
+
58
+ **영향**
59
+
60
+ - CI·스크립트·에이전트가 `bstage doctor`의 종료 코드를 보는 프로젝트. 로그인·링크가 없는 환경(포털 진단 `skipped`)은 영향이 없다.
61
+
62
+ **변경 내용**
63
+
64
+ - 포털 진단 자체가 실패하면 — 배치 목록 조회 실패, 일부 배치 진단의 권한 부족(403)·서버 오류(5xx) 등으로 `portal.status`가 `"error"`면 — 종료 코드 **1**로 끝난다. 전에는 `error` 심각도 항목이 없으면 0이라, 진단을 못 끝낸 것을 "문제 없음"으로 읽을 수 있었다.
65
+ - 그대로인 것: `error` 항목이 있으면 1, 건너뜀(`skipped`)·서버 미지원(`unsupported`)·`warn`/`info`만 있으면 0, 로컬 진단 결과는 종료 코드에 영향 없음.
66
+
67
+ **적용**
68
+
69
+ 1. (자동) CLI를 올린다. 종료 코드 1을 실패로 처리하던 CI는 그대로 동작한다. 1이 나오면 `--json`의 `portal.status`·`portal.reason`·`portal.placements[].error`로 원인을 본다(권한 부족이면 스테이지 관리 권한이 있는 계정·토큰인지 확인).
70
+
71
+ ### 어드민 템플릿도 `BstageClient`로 어드민 API를 부른다(에이전트 안내 정정) — `자동`
72
+
73
+ **영향**
74
+
75
+ - 코드·빌드 동작은 바뀌지 않는다. 에이전트 안내 문서만 바로잡았다.
76
+ - `AGENTS.md` 관리 영역과 `bstage-template` 스킬이 "BstageClient는 유저단 API만 지원하고 어드민용 API는 미지원"이라고 안내했다. 어드민 게이트웨이가 열린 지금 이 문구를 따르면 에이전트가 어드민 템플릿의 데이터 호출을 거부하거나 사용자 확인을 되풀이한다.
77
+
78
+ **변경 내용**
79
+
80
+ - 어드민 템플릿도 같은 `BstageClient`를 쓴다. 어드민 도메인에 임베드되면 `baseUrl` 기본값이 어드민 게이트웨이(`/gw`)가 되고, 게이트웨이가 어드민 로그인 쿠키와 MANAGEMENT 키(`bsm_`)를 함께 확인한다. PUBLIC 키로는 `KEY_TYPE_NOT_ALLOWED`다.
81
+ - 호출 가능한 경로는 포털 API 레퍼런스(유저/운영자 탭)에 있는 것뿐이며, 목록에 없는 API는 경로를 추측하지 말고 사용자에게 먼저 확인한다는 안내는 그대로다.
82
+ - **AGENTS.md 관리 영역 v17**: 파일 트리의 `client.ts` 설명과 API 금지 사항 절을 위 내용으로 고쳤다. `bstage-template` 스킬도 같은 내용으로 고쳤다. 상세는 [GETTING_STARTED.md](./GETTING_STARTED.md) "8. 어드민 템플릿 › API 호출".
83
+
84
+ **적용**
85
+
86
+ 1. (자동) `npx @bstage-sdk/cli@latest ai update` — 스킬·`AGENTS.md` 관리 영역을 v17로 갱신한다.
87
+
88
+ ## → cli 0.8.4 · ai-toolkit 0.8.4
89
+
90
+ ### `bstage doctor`가 포털 배치 진단을 함께 본다 — `자동` · `선택`
91
+
92
+ **영향**
93
+
94
+ - 로그인(`bstage login`)·링크(`bstage link`)된 디렉터리에서 `bstage doctor`를 실행하는 모든 프로젝트. 로그인·링크가 없으면 지금과 같다(포털 진단 절만 "건너뜀"으로 표시).
95
+ - **종료 코드가 새로 생긴다.** 포털 진단에 `error` 심각도 항목이 하나라도 있으면 `bstage doctor`가 **1**로 끝난다. 예전엔 항상 0이었다. CI·스크립트에서 doctor의 종료 코드를 실패로 처리하고 있다면 확인한다(로컬 진단 결과는 여전히 종료 코드에 영향이 없다).
96
+ - 감지: `bstage doctor --json` 출력에 `portal` 필드가 있으면 이 버전 이상이다.
97
+
98
+ **변경 내용**
99
+
100
+ - 로컬 진단 뒤에 **"포털 진단"** 절이 붙는다. 이 레포(링크된 레포)의 배치마다 포털이 판정한 문제를 심각도(`✗` error · `!` warn · `·` info), 제목, 상세, 조치와 함께 보여 준다 — 스테이지 커스텀 페이지 꺼짐, 배치 게시 꺼짐, 게시된 빌드 없음, 게시 빌드의 APP ID·KEY 문제(만료·스코프·짝 불일치·앞뒤 공백), 다시 빌드하지 않은 환경변수, 반영하지 않은 새 성공 빌드, 최신 빌드 실패 등. 문제가 없으면 `✓ 문제 없음`이다.
101
+ - 배치는 30개까지(동시 4개) 진단한다. **`--placement <id|경로|슬롯 id>`**로 하나만 볼 수 있다(`bstage deploy --placement`와 같은 정확 일치). `--placement`를 줬는데 링크가 없으면 종료 코드 2, 토큰이 없으면 3이다.
102
+ - `--json`(stdout 객체 하나)에 **`portal`** 필드가 더해진다(기존 필드는 그대로): `{ status: 'ok'|'skipped'|'unsupported'|'error', reason?, hint?, omitted?, placements: [{ placementId, path, slotId, surface, findings: [{ id, severity, title, detail?, fix?, evidence? }], error? }] }`. `findings[].id`(예: `appkey.expired`, `placement.not_deployed`)는 바뀌지 않는 식별자라 스크립트·에이전트가 분기에 쓸 수 있다. 진단 요청이 실패한 배치는 `error`에 이유가 담기고 `status`는 `error`다.
103
+ - 포털 서버가 아직 진단을 지원하지 않으면(`status: 'unsupported'`) 그 절만 건너뛴다. CLI 토큰은 `read` 등급이면 된다.
104
+ - `bstage-deploy` 스킬: 배포 후 401이 나거나 페이지가 기대와 다르면 `bstage doctor --json`부터 실행해 `portal.placements[].findings`의 `id`·`fix`를 따르도록 안내한다.
105
+
106
+ **적용**
107
+
108
+ 1. (자동) CLI를 올리면 된다. 스킬 문구는 `npx @bstage-sdk/cli@latest ai update`로 갱신한다.
109
+ 2. (판단) CI에서 `bstage doctor`를 돌리고 있다면 새 종료 코드 1을 실패로 볼지 정한다. 로그인·링크가 없는 CI라면 영향이 없다.
110
+
54
111
  ## → cli 0.8.3 · ai-toolkit 0.8.3
55
112
 
56
113
  ### sandbox 포털 기본 주소가 공개 주소로 바뀌었다 — `자동`
package/dist/index.js CHANGED
@@ -156,6 +156,18 @@ var PortalClient = class {
156
156
  );
157
157
  return unwrap(body, "placements");
158
158
  }
159
+ /**
160
+ * `GET .../placements/{id}/diagnosis` — 배치 하나가 "왜 기대대로 안 뜨는가"를 서버가 판정한 결과.
161
+ * 이 경로가 없는 구버전 서버는 404(CLI 토큰이면 등급 허용 목록 403)로 답한다 — 해석은 호출자 몫이다.
162
+ * `findings`가 빠진 응답도 빈 배열로 맞춰 호출자가 분기하지 않게 한다.
163
+ */
164
+ async getPlacementDiagnosis(org, space, placementId) {
165
+ const d = await this.json(
166
+ "GET",
167
+ `${this.stage(org, space)}/placements/${enc(placementId)}/diagnosis`
168
+ );
169
+ return { ...d, findings: d.findings ?? [] };
170
+ }
159
171
  /**
160
172
  * `expectedLiveBuildId`는 CAS(compare-and-swap) — 서버 측 live 빌드와 다르면 409.
161
173
  * 응답은 배치 전체가 아니라 `{id, liveBuildId}`만 온다(포털 핸들러 그대로).
@@ -4438,6 +4450,125 @@ async function i18nPullCommand(options) {
4438
4450
  console.log(pc15.dim(" \uC0DD\uC131 \uD30C\uC77C\uC744 \uD55C \uBC88 import\uD558\uBA74 useBstageTranslations().t() \uD0A4\uAC00 \uC881\uD600\uC9D1\uB2C8\uB2E4."));
4439
4451
  }
4440
4452
 
4453
+ // src/commands/doctor/portal.ts
4454
+ var MAX_DIAGNOSED_PLACEMENTS = 30;
4455
+ var DIAGNOSIS_CONCURRENCY = 4;
4456
+ function portalHasErrorFinding(p5) {
4457
+ return (p5?.placements ?? []).some((row) => row.findings.some((f) => f.severity === "error"));
4458
+ }
4459
+ function portalNeedsWork(p5) {
4460
+ return p5 !== void 0 && (p5.status === "error" || portalHasErrorFinding(p5));
4461
+ }
4462
+ async function diagnosePortal(opts, deps = {}) {
4463
+ const explicit = Boolean(opts.placement);
4464
+ const ctx = await openContext(deps, explicit);
4465
+ if (!("client" in ctx)) return ctx;
4466
+ const { client, link } = ctx;
4467
+ let all;
4468
+ try {
4469
+ all = await client.listPlacements(link.organizationId, link.spaceId, link.surface);
4470
+ } catch (err) {
4471
+ return {
4472
+ status: "error",
4473
+ reason: `\uBC30\uCE58 \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 ${describeError(err)}`,
4474
+ placements: []
4475
+ };
4476
+ }
4477
+ const targets = explicit ? requireTargets(all, link.repoId, opts.placement) : selectPlacements(all, link.repoId);
4478
+ if (targets.length === 0) {
4479
+ return {
4480
+ status: "ok",
4481
+ reason: "\uC774 \uB808\uD3EC\uC5D0 \uC5F0\uACB0\uB41C \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
4482
+ hint: "bstage placement create --template <\uC0B0\uCD9C\uBB3C \uC774\uB984>",
4483
+ placements: []
4484
+ };
4485
+ }
4486
+ const picked = targets.slice(0, MAX_DIAGNOSED_PLACEMENTS);
4487
+ const omitted = targets.length - picked.length;
4488
+ const outcomes = await mapLimit(picked, DIAGNOSIS_CONCURRENCY, (p5) => diagnoseOne(ctx, p5));
4489
+ if (outcomes.every((o) => o.unsupported)) {
4490
+ return {
4491
+ status: "unsupported",
4492
+ reason: "\uD3EC\uD138 \uC11C\uBC84\uAC00 \uC544\uC9C1 \uBC30\uCE58 \uC9C4\uB2E8\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
4493
+ placements: []
4494
+ };
4495
+ }
4496
+ const placements = outcomes.map((o) => o.row);
4497
+ return {
4498
+ status: placements.some((r) => r.error !== void 0) ? "error" : "ok",
4499
+ placements,
4500
+ ...omitted > 0 ? { omitted } : {}
4501
+ };
4502
+ }
4503
+ async function openContext(deps, explicit) {
4504
+ const cwd = deps.cwd ?? process.cwd();
4505
+ const env2 = deps.env ?? process.env;
4506
+ const hasLink = await loadLink(cwd, env2) !== null;
4507
+ try {
4508
+ return await resolveContext({ cwd, env: env2, fetch: deps.fetch });
4509
+ } catch (err) {
4510
+ if (explicit) throw err;
4511
+ const reason = scrub(err instanceof Error ? err.message : String(err));
4512
+ const isAuth = err instanceof CliExit && err.code === ExitCode.AUTH;
4513
+ const hint = isAuth ? "bstage login" : hasLink ? void 0 : "bstage link";
4514
+ return { status: "skipped", reason, ...hint ? { hint } : {}, placements: [] };
4515
+ }
4516
+ }
4517
+ async function diagnoseOne(ctx, p5) {
4518
+ const base = {
4519
+ placementId: p5.id,
4520
+ path: p5.path ?? "",
4521
+ slotId: p5.slotId ?? "",
4522
+ surface: p5.surface
4523
+ };
4524
+ try {
4525
+ const d = await ctx.client.getPlacementDiagnosis(
4526
+ ctx.link.organizationId,
4527
+ ctx.link.spaceId,
4528
+ p5.id
4529
+ );
4530
+ return {
4531
+ row: {
4532
+ ...base,
4533
+ path: d.path || base.path,
4534
+ slotId: d.slotId || base.slotId,
4535
+ surface: d.surface ?? base.surface,
4536
+ findings: d.findings
4537
+ },
4538
+ unsupported: false
4539
+ };
4540
+ } catch (err) {
4541
+ return {
4542
+ row: { ...base, findings: [], error: describeError(err) },
4543
+ unsupported: isUnsupported(err)
4544
+ };
4545
+ }
4546
+ }
4547
+ var PLACEMENT_NOT_FOUND = "\uBC30\uCE58\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4";
4548
+ function isUnsupported(err) {
4549
+ if (!(err instanceof PortalError)) return false;
4550
+ if (err.status === 404) return !err.message.includes(PLACEMENT_NOT_FOUND);
4551
+ return err.status === 403 && err.message.includes("\uD1A0\uD070 \uB4F1\uAE09\uC73C\uB85C \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294");
4552
+ }
4553
+ function describeError(err) {
4554
+ if (err instanceof PortalError && err.status > 0) {
4555
+ return scrub(`${err.message} (HTTP ${err.status})`);
4556
+ }
4557
+ return scrub(err instanceof Error ? err.message : String(err));
4558
+ }
4559
+ async function mapLimit(items, limit, fn) {
4560
+ const results = new Array(items.length);
4561
+ let next = 0;
4562
+ const worker = async () => {
4563
+ while (next < items.length) {
4564
+ const i = next++;
4565
+ results[i] = await fn(items[i]);
4566
+ }
4567
+ };
4568
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
4569
+ return results;
4570
+ }
4571
+
4441
4572
  // src/commands/doctor/report.ts
4442
4573
  import { readFile as readFile9 } from "fs/promises";
4443
4574
  import { join as join15 } from "path";
@@ -4839,18 +4970,90 @@ async function fetchLatestVersion2(packageName) {
4839
4970
  }
4840
4971
 
4841
4972
  // src/commands/doctor/render.ts
4973
+ import pc17 from "picocolors";
4974
+
4975
+ // src/commands/doctor/renderPortal.ts
4842
4976
  import pc16 from "picocolors";
4977
+ var MARKERS = {
4978
+ error: pc16.red("\u2717"),
4979
+ warn: pc16.yellow("!"),
4980
+ info: pc16.dim("\xB7")
4981
+ };
4982
+ function clean(s) {
4983
+ return (s ?? "").replace(/\t/g, " ").replace(/[\p{Cc}\p{Cf}\p{Co}\p{Cs}\p{Zl}\p{Zp}\p{Variation_Selector}\u00ad\u180e]/gu, "");
4984
+ }
4985
+ function marker(severity) {
4986
+ return MARKERS[severity] ?? pc16.dim("\xB7");
4987
+ }
4988
+ function hintSuffix(reason, hint) {
4989
+ return hint && !(reason ?? "").includes(hint) ? ` (\uD560 \uC77C: ${hint})` : "";
4990
+ }
4991
+ function formatFinding(f) {
4992
+ const lines = [` ${marker(f.severity)} ${clean(f.title)} ${pc16.dim(`[${clean(f.id)}]`)}`];
4993
+ if (f.detail) lines.push(pc16.dim(` ${clean(f.detail)}`));
4994
+ if (f.fix) lines.push(pc16.dim(` \uC870\uCE58: ${clean(f.fix)}`));
4995
+ return lines;
4996
+ }
4997
+ function formatPlacement(row) {
4998
+ const label = clean(row.path || row.slotId || row.placementId);
4999
+ const lines = [` ${pc16.bold(label)}`];
5000
+ if (row.error !== void 0) {
5001
+ lines.push(` ${pc16.red("\u2717")} \uC9C4\uB2E8\uC744 \uBC1B\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 ${clean(row.error)}`);
5002
+ } else if (row.findings.length === 0) {
5003
+ lines.push(` ${pc16.green("\u2713")} \uBB38\uC81C \uC5C6\uC74C`);
5004
+ } else {
5005
+ lines.push(...row.findings.flatMap(formatFinding));
5006
+ }
5007
+ return lines;
5008
+ }
5009
+ function formatPortal(p5) {
5010
+ const lines = [pc16.bold("\uD3EC\uD138 \uC9C4\uB2E8")];
5011
+ if (p5.status === "skipped") {
5012
+ lines.push(
5013
+ pc16.dim(
5014
+ ` \uAC74\uB108\uB700 \u2014 ${clean(p5.reason) || "\uB85C\uADF8\uC778\xB7\uB9C1\uD06C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."}${hintSuffix(p5.reason, p5.hint)}`
5015
+ )
5016
+ );
5017
+ } else if (p5.status === "unsupported") {
5018
+ lines.push(
5019
+ pc16.dim(` \uAC74\uB108\uB700 \u2014 ${clean(p5.reason) || "\uD3EC\uD138 \uC11C\uBC84\uAC00 \uC544\uC9C1 \uC9C4\uB2E8\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."}`)
5020
+ );
5021
+ } else if (p5.placements.length === 0) {
5022
+ lines.push(
5023
+ p5.status === "error" ? pc16.red(` \u2717 ${clean(p5.reason) || "\uD3EC\uD138 \uC9C4\uB2E8\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."}`) : pc16.dim(
5024
+ ` ${clean(p5.reason) || "\uC9C4\uB2E8\uD560 \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."}${hintSuffix(p5.reason, p5.hint)}`
5025
+ )
5026
+ );
5027
+ } else {
5028
+ lines.push(...p5.placements.flatMap(formatPlacement));
5029
+ }
5030
+ if (p5.omitted) {
5031
+ lines.push(
5032
+ pc16.dim(
5033
+ ` (\uBC30\uCE58\uAC00 \uB9CE\uC544 ${p5.omitted}\uAC1C\uB294 \uC9C4\uB2E8\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 bstage doctor --placement <\uACBD\uB85C|\uC2AC\uB86F id>\uB85C \uB530\uB85C \uBCF4\uC138\uC694.)`
5034
+ )
5035
+ );
5036
+ }
5037
+ return lines;
5038
+ }
5039
+ function printPortal(p5) {
5040
+ if (!p5) return;
5041
+ for (const line of formatPortal(p5)) console.log(line);
5042
+ console.log("");
5043
+ }
5044
+
5045
+ // src/commands/doctor/render.ts
4843
5046
  function printVersions(r) {
4844
- console.log(pc16.bold("\u{1F4E6} SDK \uBC84\uC804"));
5047
+ console.log(pc17.bold("\u{1F4E6} SDK \uBC84\uC804"));
4845
5048
  if (!r.latestChecked) {
4846
- console.log(pc16.dim(" \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uAC74\uB108\uB6F0\uC5B4 \uC124\uCE58 \uBC84\uC804\uB9CC \uD45C\uC2DC\uD569\uB2C8\uB2E4."));
5049
+ console.log(pc17.dim(" \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uAC74\uB108\uB6F0\uC5B4 \uC124\uCE58 \uBC84\uC804\uB9CC \uD45C\uC2DC\uD569\uB2C8\uB2E4."));
4847
5050
  }
4848
5051
  const nameWidth = Math.max(12, ...r.versions.map((v) => v.pkg.replace("@bstage-sdk/", "").length));
4849
5052
  for (const v of r.versions) {
4850
5053
  const name = v.pkg.replace("@bstage-sdk/", "").padEnd(nameWidth);
4851
5054
  const inst = v.installed ?? "?";
4852
5055
  if (v.latest && v.installed) {
4853
- const arrow = v.outdated ? pc16.yellow(`\u2192 ${v.latest} (\uB4A4\uCC98\uC9D0)`) : pc16.green("(\uCD5C\uC2E0)");
5056
+ const arrow = v.outdated ? pc17.yellow(`\u2192 ${v.latest} (\uB4A4\uCC98\uC9D0)`) : pc17.green("(\uCD5C\uC2E0)");
4854
5057
  console.log(` ${name} ${inst.padEnd(8)} ${arrow}`);
4855
5058
  } else {
4856
5059
  console.log(` ${name} ${inst}`);
@@ -4859,89 +5062,89 @@ function printVersions(r) {
4859
5062
  console.log("");
4860
5063
  }
4861
5064
  function printFiles(r) {
4862
- console.log(pc16.bold("\u{1F4C1} init \uAE30\uBCF8 \uD30C\uC77C (\uCC38\uACE0)"));
5065
+ console.log(pc17.bold("\u{1F4C1} init \uAE30\uBCF8 \uD30C\uC77C (\uCC38\uACE0)"));
4863
5066
  const absent = r.files.filter((f) => !f.present);
4864
5067
  if (absent.length === 0) {
4865
- console.log(pc16.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
5068
+ console.log(pc17.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
4866
5069
  } else {
4867
- console.log(pc16.dim(" init \uAE30\uBCF8\uAC12\uACFC\uC758 \uCC28\uC774\uC77C \uBFD0 \u2014 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB2E4\uB974\uAC8C \uCC98\uB9AC \uC911\uC774\uBA74 \uBB34\uC2DC\uD558\uC138\uC694."));
5070
+ console.log(pc17.dim(" init \uAE30\uBCF8\uAC12\uACFC\uC758 \uCC28\uC774\uC77C \uBFD0 \u2014 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB2E4\uB974\uAC8C \uCC98\uB9AC \uC911\uC774\uBA74 \uBB34\uC2DC\uD558\uC138\uC694."));
4868
5071
  for (const f of r.files) {
4869
- if (f.present) console.log(` ${pc16.green("\u2713")} ${f.path}`);
4870
- else console.log(` ${pc16.dim("\xB7")} ${f.path.padEnd(20)} ${pc16.dim(`\uC5C6\uC74C (${f.note})`)}`);
5072
+ if (f.present) console.log(` ${pc17.green("\u2713")} ${f.path}`);
5073
+ else console.log(` ${pc17.dim("\xB7")} ${f.path.padEnd(20)} ${pc17.dim(`\uC5C6\uC74C (${f.note})`)}`);
4871
5074
  }
4872
5075
  }
4873
5076
  console.log("");
4874
5077
  }
4875
5078
  function printLayout(r) {
4876
- console.log(pc16.bold("\u{1F5C2} \uD15C\uD50C\uB9BF \uB514\uB809\uD1A0\uB9AC"));
5079
+ console.log(pc17.bold("\u{1F5C2} \uD15C\uD50C\uB9BF \uB514\uB809\uD1A0\uB9AC"));
4877
5080
  if (r.layout.legacyPresent) {
4878
- console.log(` ${pc16.yellow("\u2192")} ${pc16.yellow("src/templates/ \uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 (\uC61B \uAD6C\uC870)")}`);
4879
- console.log(pc16.dim(" \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C \uACBD\uB85C\uAC00 \uD3F4\uB354 \uAD6C\uC870\uB97C \uB530\uB77C\uAC00\uB3C4\uB85D \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4."));
4880
- console.log(pc16.dim(" \uD398\uC774\uC9C0 \u2192 src/pages/{\uACBD\uB85C}/ \xB7 \uC704\uC82F \u2192 src/slots/{\uC544\uBB34\uC774\uB984}/"));
5081
+ console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("src/templates/ \uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 (\uC61B \uAD6C\uC870)")}`);
5082
+ console.log(pc17.dim(" \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C \uACBD\uB85C\uAC00 \uD3F4\uB354 \uAD6C\uC870\uB97C \uB530\uB77C\uAC00\uB3C4\uB85D \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4."));
5083
+ console.log(pc17.dim(" \uD398\uC774\uC9C0 \u2192 src/pages/{\uACBD\uB85C}/ \xB7 \uC704\uC82F \u2192 src/slots/{\uC544\uBB34\uC774\uB984}/"));
4881
5084
  if (r.layout.legacyTemplates.length > 0) {
4882
- console.log(pc16.dim(` \uC62E\uACA8\uC57C \uD560 \uD15C\uD50C\uB9BF: ${r.layout.legacyTemplates.join(", ")}`));
5085
+ console.log(pc17.dim(` \uC62E\uACA8\uC57C \uD560 \uD15C\uD50C\uB9BF: ${r.layout.legacyTemplates.join(", ")}`));
4883
5086
  }
4884
- console.log(pc16.dim(' \uBCC0\uD658: \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C "bstage \uB9C8\uC774\uADF8\uB808\uC774\uC158" \uC694\uCCAD'));
5087
+ console.log(pc17.dim(' \uBCC0\uD658: \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C "bstage \uB9C8\uC774\uADF8\uB808\uC774\uC158" \uC694\uCCAD'));
4885
5088
  } else if (!r.layout.pagesPresent && !r.layout.slotsPresent) {
4886
- console.log(` ${pc16.dim("\xB7")} src/pages/ \xB7 src/slots/ \uB458 \uB2E4 \uC5C6\uC74C`);
5089
+ console.log(` ${pc17.dim("\xB7")} src/pages/ \xB7 src/slots/ \uB458 \uB2E4 \uC5C6\uC74C`);
4887
5090
  } else {
4888
- console.log(pc16.green(" \u2713 src/pages/ \xB7 src/slots/ \uAD6C\uC870"));
5091
+ console.log(pc17.green(" \u2713 src/pages/ \xB7 src/slots/ \uAD6C\uC870"));
4889
5092
  }
4890
5093
  console.log("");
4891
5094
  }
4892
5095
  function printPnpmWorkspace(r) {
4893
5096
  if (!r.pnpmWorkspace.relevant) return;
4894
- console.log(pc16.bold("\u{1F4E6} pnpm workspace \uC124\uC815"));
5097
+ console.log(pc17.bold("\u{1F4E6} pnpm workspace \uC124\uC815"));
4895
5098
  if (r.pnpmWorkspace.allowBuildsDeclared) {
4896
- console.log(pc16.green(" \u2713 pnpm-workspace.yaml\uC5D0 allowBuilds \uC120\uC5B8\uB428"));
5099
+ console.log(pc17.green(" \u2713 pnpm-workspace.yaml\uC5D0 allowBuilds \uC120\uC5B8\uB428"));
4897
5100
  } else {
4898
- console.log(` ${pc16.yellow("\u2192")} ${pc16.yellow("pnpm-workspace.yaml\uC5D0 allowBuilds \uC5C6\uC74C")}`);
5101
+ console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("pnpm-workspace.yaml\uC5D0 allowBuilds \uC5C6\uC74C")}`);
4899
5102
  console.log(
4900
- pc16.dim(" pnpm\uC740 \uC758\uC874\uC131 build script\uB97C \uAE30\uBCF8 \uCC28\uB2E8\uD558\uACE0, pnpm 11\uC740 \uADF8\uAC83\uC744 \uC5D0\uB7EC\uB85C \uB0B8\uB2E4")
5103
+ pc17.dim(" pnpm\uC740 \uC758\uC874\uC131 build script\uB97C \uAE30\uBCF8 \uCC28\uB2E8\uD558\uACE0, pnpm 11\uC740 \uADF8\uAC83\uC744 \uC5D0\uB7EC\uB85C \uB0B8\uB2E4")
4901
5104
  );
4902
5105
  console.log(
4903
- pc16.dim(" \u2192 `pnpm install`\uC774 ERR_PNPM_IGNORED_BUILDS\uB85C \uC2E4\uD328\uD558\uACE0 `pnpm dev`\uB3C4 \uC8FD\uB294\uB2E4")
5106
+ pc17.dim(" \u2192 `pnpm install`\uC774 ERR_PNPM_IGNORED_BUILDS\uB85C \uC2E4\uD328\uD558\uACE0 `pnpm dev`\uB3C4 \uC8FD\uB294\uB2E4")
4904
5107
  );
4905
- console.log(pc16.dim(" \uCD94\uAC00: pnpm-workspace.yaml\uC5D0 `allowBuilds:` + `esbuild: true`"));
4906
- console.log(pc16.dim(" \uB610\uB294 `pnpm approve-builds`\uB85C \uB300\uD654\uC2DD \uC120\uD0DD"));
5108
+ console.log(pc17.dim(" \uCD94\uAC00: pnpm-workspace.yaml\uC5D0 `allowBuilds:` + `esbuild: true`"));
5109
+ console.log(pc17.dim(" \uB610\uB294 `pnpm approve-builds`\uB85C \uB300\uD654\uC2DD \uC120\uD0DD"));
4907
5110
  }
4908
5111
  if (r.pnpmWorkspace.filePresent && !r.pnpmWorkspace.packagesDeclared) {
4909
- console.log(` ${pc16.yellow("\u2192")} ${pc16.yellow("pnpm-workspace.yaml\uC5D0 packages \uC5C6\uC74C")}`);
4910
- console.log(pc16.dim(" pnpm 9\uB294 \uC774 \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 workspace \uB8E8\uD2B8\uB85C \uBCF4\uACE0 packages\uB97C \uC694\uAD6C\uD55C\uB2E4"));
4911
- console.log(pc16.dim(" \u2192 pnpm 9\uC5D0\uC11C `ERROR packages field missing or empty`\uB85C \uC8FD\uB294\uB2E4"));
4912
- console.log(pc16.dim(" \uCD94\uAC00: pnpm-workspace.yaml \uB9E8 \uC704\uC5D0 `packages:` + `- '.'`"));
5112
+ console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("pnpm-workspace.yaml\uC5D0 packages \uC5C6\uC74C")}`);
5113
+ console.log(pc17.dim(" pnpm 9\uB294 \uC774 \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 workspace \uB8E8\uD2B8\uB85C \uBCF4\uACE0 packages\uB97C \uC694\uAD6C\uD55C\uB2E4"));
5114
+ console.log(pc17.dim(" \u2192 pnpm 9\uC5D0\uC11C `ERROR packages field missing or empty`\uB85C \uC8FD\uB294\uB2E4"));
5115
+ console.log(pc17.dim(" \uCD94\uAC00: pnpm-workspace.yaml \uB9E8 \uC704\uC5D0 `packages:` + `- '.'`"));
4913
5116
  } else if (r.pnpmWorkspace.packagesDeclared) {
4914
- console.log(pc16.green(" \u2713 pnpm-workspace.yaml\uC5D0 packages \uC120\uC5B8\uB428"));
5117
+ console.log(pc17.green(" \u2713 pnpm-workspace.yaml\uC5D0 packages \uC120\uC5B8\uB428"));
4915
5118
  }
4916
5119
  console.log("");
4917
5120
  }
4918
5121
  function printScriptRow(sc) {
4919
5122
  if (sc.actual === null) {
4920
- console.log(` ${pc16.yellow("\u2192")} ${sc.name} ${pc16.yellow("\uC5C6\uC74C")}`);
5123
+ console.log(` ${pc17.yellow("\u2192")} ${sc.name} ${pc17.yellow("\uC5C6\uC74C")}`);
4921
5124
  } else {
4922
5125
  console.log(
4923
- ` ${pc16.yellow("\u2192")} ${sc.name} ${pc16.yellow("\uB2E4\uB984")} ${pc16.dim(`\u2014 \uD604\uC7AC \`${sc.actual}\``)}`
5126
+ ` ${pc17.yellow("\u2192")} ${sc.name} ${pc17.yellow("\uB2E4\uB984")} ${pc17.dim(`\u2014 \uD604\uC7AC \`${sc.actual}\``)}`
4924
5127
  );
4925
5128
  if (sc.actual.includes("--noEmit") && !sc.actual.includes("-p ")) {
4926
5129
  console.log(
4927
- pc16.dim(
5130
+ pc17.dim(
4928
5131
  " \uC8FC\uC758: solution-style tsconfig\uC5D0\uC11C `tsc --noEmit`\uC740 \uC544\uBB34 \uD30C\uC77C\uB3C4 \uAC80\uC0AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
4929
5132
  )
4930
5133
  );
4931
5134
  }
4932
5135
  }
4933
- console.log(pc16.dim(` ${sc.why}`));
4934
- console.log(pc16.dim(` \uAD8C\uC7A5: "${sc.name}": "${sc.expected}"`));
5136
+ console.log(pc17.dim(` ${sc.why}`));
5137
+ console.log(pc17.dim(` \uAD8C\uC7A5: "${sc.name}": "${sc.expected}"`));
4935
5138
  }
4936
5139
  function printScripts(r) {
4937
- console.log(pc16.bold("\u{1F6E0} package.json \uC2A4\uD06C\uB9BD\uD2B8"));
5140
+ console.log(pc17.bold("\u{1F6E0} package.json \uC2A4\uD06C\uB9BD\uD2B8"));
4938
5141
  const scriptIssues = r.scripts.filter((sc) => sc.actual !== sc.expected);
4939
5142
  if (scriptIssues.length === 0) {
4940
- console.log(pc16.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
5143
+ console.log(pc17.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
4941
5144
  } else {
4942
5145
  for (const sc of r.scripts) {
4943
5146
  if (sc.actual === sc.expected) {
4944
- console.log(` ${pc16.green("\u2713")} ${sc.name}`);
5147
+ console.log(` ${pc17.green("\u2713")} ${sc.name}`);
4945
5148
  continue;
4946
5149
  }
4947
5150
  printScriptRow(sc);
@@ -4951,76 +5154,76 @@ function printScripts(r) {
4951
5154
  }
4952
5155
  function printLiquid(r) {
4953
5156
  if (r.liquid === null) return;
4954
- console.log(pc16.bold("\u{1F4A7} liquid \uAC80\uC99D"));
5157
+ console.log(pc17.bold("\u{1F4A7} liquid \uAC80\uC99D"));
4955
5158
  const errors = r.liquid.issues.filter((i) => i.level === "error");
4956
5159
  const warns = r.liquid.issues.filter((i) => i.level === "warn");
4957
5160
  if (errors.length === 0 && warns.length === 0) {
4958
- console.log(pc16.green(" \u2713 \uADDC\uC57D\xB7\uBB38\uBC95 \uC774\uC0C1 \uC5C6\uC74C"));
5161
+ console.log(pc17.green(" \u2713 \uADDC\uC57D\xB7\uBB38\uBC95 \uC774\uC0C1 \uC5C6\uC74C"));
4959
5162
  }
4960
- for (const i of errors) console.log(` ${pc16.red("\u2717")} ${i.path} ${pc16.red(i.message)}`);
4961
- for (const i of warns) console.log(` ${pc16.yellow("\u26A0")} ${i.path} ${pc16.dim(i.message)}`);
5163
+ for (const i of errors) console.log(` ${pc17.red("\u2717")} ${i.path} ${pc17.red(i.message)}`);
5164
+ for (const i of warns) console.log(` ${pc17.yellow("\u26A0")} ${i.path} ${pc17.dim(i.message)}`);
4962
5165
  if (errors.length > 0) {
4963
5166
  console.log(
4964
- pc16.dim(" \uACE0\uCE5C \uB4A4 `bstage build`\uB85C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694 \u2014 \uD3EC\uD138 \uBE4C\uB4DC\uB3C4 \uAC19\uC740 \uAC80\uC0AC\uB97C \uD569\uB2C8\uB2E4.")
5167
+ pc17.dim(" \uACE0\uCE5C \uB4A4 `bstage build`\uB85C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694 \u2014 \uD3EC\uD138 \uBE4C\uB4DC\uB3C4 \uAC19\uC740 \uAC80\uC0AC\uB97C \uD569\uB2C8\uB2E4.")
4965
5168
  );
4966
5169
  }
4967
5170
  console.log("");
4968
5171
  }
4969
5172
  function printRecommendedDeps(r) {
4970
5173
  if (r.recommendedDeps.length === 0) return;
4971
- console.log(pc16.bold("\u{1F9F1} \uAD8C\uC7A5 \uC758\uC874\uC131"));
5174
+ console.log(pc17.bold("\u{1F9F1} \uAD8C\uC7A5 \uC758\uC874\uC131"));
4972
5175
  if (r.recommendedDeps.every((d) => d.declared)) {
4973
- console.log(pc16.green(" \u2713 \uBAA8\uB450 \uC120\uC5B8\uB428"));
5176
+ console.log(pc17.green(" \u2713 \uBAA8\uB450 \uC120\uC5B8\uB428"));
4974
5177
  } else {
4975
5178
  for (const d of r.recommendedDeps) {
4976
5179
  if (d.declared) {
4977
- console.log(` ${pc16.green("\u2713")} ${d.pkg}`);
5180
+ console.log(` ${pc17.green("\u2713")} ${d.pkg}`);
4978
5181
  continue;
4979
5182
  }
4980
- console.log(` ${pc16.yellow("\u2192")} ${d.pkg} ${pc16.yellow("\uBBF8\uC120\uC5B8")} ${pc16.dim(`\u2014 ${d.note}`)}`);
4981
- console.log(pc16.dim(` ${d.why}`));
4982
- console.log(pc16.dim(` \uCD94\uAC00: npm i ${d.pkg} (\uD504\uB85C\uC81D\uD2B8 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB85C)`));
5183
+ console.log(` ${pc17.yellow("\u2192")} ${d.pkg} ${pc17.yellow("\uBBF8\uC120\uC5B8")} ${pc17.dim(`\u2014 ${d.note}`)}`);
5184
+ console.log(pc17.dim(` ${d.why}`));
5185
+ console.log(pc17.dim(` \uCD94\uAC00: npm i ${d.pkg} (\uD504\uB85C\uC81D\uD2B8 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB85C)`));
4983
5186
  }
4984
5187
  }
4985
5188
  console.log("");
4986
5189
  }
4987
5190
  function printMigrations(r) {
4988
- console.log(pc16.bold("\u{1F4D6} \uC801\uC6A9 \uAC00\uB2A5\uD55C \uB9C8\uC774\uADF8\uB808\uC774\uC158"));
5191
+ console.log(pc17.bold("\u{1F4D6} \uC801\uC6A9 \uAC00\uB2A5\uD55C \uB9C8\uC774\uADF8\uB808\uC774\uC158"));
4989
5192
  if (r.migrations.length === 0) {
4990
- console.log(pc16.dim(" \uD574\uB2F9 \uD56D\uBAA9 \uC5C6\uC74C."));
5193
+ console.log(pc17.dim(" \uD574\uB2F9 \uD56D\uBAA9 \uC5C6\uC74C."));
4991
5194
  } else {
4992
5195
  for (const m of r.migrations) {
4993
- console.log(` ${pc16.cyan(`\u2192 ${m.label}`)}`);
5196
+ console.log(` ${pc17.cyan(`\u2192 ${m.label}`)}`);
4994
5197
  for (const item of m.items) console.log(` \u2022 ${item}`);
4995
5198
  }
4996
5199
  }
4997
5200
  console.log("");
4998
5201
  }
4999
5202
  function printAgentsMd(r) {
5000
- console.log(pc16.bold("\u{1F4DD} AGENTS.md"));
5203
+ console.log(pc17.bold("\u{1F4DD} AGENTS.md"));
5001
5204
  switch (r.agentsMd.status) {
5002
5205
  case "ok":
5003
- console.log(pc16.green(" \u2713 \uAD00\uB9AC \uC601\uC5ED \uCD5C\uC2E0"));
5206
+ console.log(pc17.green(" \u2713 \uAD00\uB9AC \uC601\uC5ED \uCD5C\uC2E0"));
5004
5207
  break;
5005
5208
  case "missing":
5006
- console.log(pc16.dim(" \xB7 \uD30C\uC77C \uC5C6\uC74C \u2014 bstage \uD504\uB85C\uC81D\uD2B8\uB77C\uBA74 init/\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC73C\uB85C \uC0DD\uC131\uD558\uC138\uC694."));
5209
+ console.log(pc17.dim(" \xB7 \uD30C\uC77C \uC5C6\uC74C \u2014 bstage \uD504\uB85C\uC81D\uD2B8\uB77C\uBA74 init/\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC73C\uB85C \uC0DD\uC131\uD558\uC138\uC694."));
5007
5210
  break;
5008
5211
  case "stale":
5009
5212
  if (r.agentsMd.downgrade) {
5010
5213
  console.log(
5011
- pc16.yellow(" ! \uAD00\uB9AC \uC601\uC5ED\uC774 \uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804") + pc16.dim(
5214
+ pc17.yellow(" ! \uAD00\uB9AC \uC601\uC5ED\uC774 \uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804") + pc17.dim(
5012
5215
  " \u2014 \uC774 CLI\uAC00 \uC624\uB798\uB3FC \uAC31\uC2E0\uD558\uBA74 \uC61B \uBCF8\uBB38\uC73C\uB85C \uB418\uB3CC\uC544\uAC11\uB2C8\uB2E4(\uD558\uD5A5). \uCD5C\uC2E0 CLI(npx @bstage-sdk/cli@latest)\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
5013
5216
  )
5014
5217
  );
5015
5218
  break;
5016
5219
  }
5017
5220
  console.log(
5018
- pc16.yellow(" \u2192 \uAD00\uB9AC \uC601\uC5ED\uC774 \uC624\uB798\uB428") + pc16.dim(" \u2014 `bstage ai update`\uB85C \uAC31\uC2E0(\uC790\uC720 \uC601\uC5ED\uC740 \uBCF4\uC874).")
5221
+ pc17.yellow(" \u2192 \uAD00\uB9AC \uC601\uC5ED\uC774 \uC624\uB798\uB428") + pc17.dim(" \u2014 `bstage ai update`\uB85C \uAC31\uC2E0(\uC790\uC720 \uC601\uC5ED\uC740 \uBCF4\uC874).")
5019
5222
  );
5020
5223
  break;
5021
5224
  case "legacy":
5022
5225
  console.log(
5023
- pc16.yellow(" \u2192 \uB808\uAC70\uC2DC \uD3EC\uB9F7(\uAD00\uB9AC \uC601\uC5ED \uB9C8\uCEE4 \uC5C6\uC74C)") + pc16.dim(
5226
+ pc17.yellow(" \u2192 \uB808\uAC70\uC2DC \uD3EC\uB9F7(\uAD00\uB9AC \uC601\uC5ED \uB9C8\uCEE4 \uC5C6\uC74C)") + pc17.dim(
5024
5227
  " \u2014 `bstage ai install`\uB85C \uC2A4\uD0AC\uC744 \uBA3C\uC800 \uC124\uCE58\uD55C \uB4A4, `bstage-migrate` \uC2A4\uD0AC\uB85C reconcile(SDK \uC601\uC5ED \uAD50\uCCB4 + \uC0AC\uC6A9\uC790 \uB0B4\uC6A9 \uBCF4\uC874)."
5025
5228
  )
5026
5229
  );
@@ -5029,29 +5232,29 @@ function printAgentsMd(r) {
5029
5232
  console.log("");
5030
5233
  }
5031
5234
  function printSkills(r) {
5032
- console.log(pc16.bold("\u{1F9E9} \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC (.claude/skills/)"));
5235
+ console.log(pc17.bold("\u{1F9E9} \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC (.claude/skills/)"));
5033
5236
  const skillsNeedWork = r.skills.filter((s) => s.status !== "ok");
5034
5237
  if (r.skillsSkipped) {
5035
5238
  console.log(
5036
- pc16.yellow(" ! sdk\uC640 liquid\uAC00 \uC11E\uC5EC \uC788\uC5B4 \uC2A4\uD0AC \uAC80\uC0AC\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 \uD558\uB098\uB9CC \uB0A8\uACA8 \uC8FC\uC138\uC694.")
5239
+ pc17.yellow(" ! sdk\uC640 liquid\uAC00 \uC11E\uC5EC \uC788\uC5B4 \uC2A4\uD0AC \uAC80\uC0AC\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 \uD558\uB098\uB9CC \uB0A8\uACA8 \uC8FC\uC138\uC694.")
5037
5240
  );
5038
5241
  } else if (skillsNeedWork.length === 0) {
5039
- console.log(pc16.green(" \u2713 \uBAA8\uB4E0 \uC2A4\uD0AC \uCD5C\uC2E0"));
5242
+ console.log(pc17.green(" \u2713 \uBAA8\uB4E0 \uC2A4\uD0AC \uCD5C\uC2E0"));
5040
5243
  } else {
5041
5244
  for (const s of r.skills) {
5042
- if (s.status === "ok") console.log(` ${pc16.green("\u2713")} ${s.name}`);
5245
+ if (s.status === "ok") console.log(` ${pc17.green("\u2713")} ${s.name}`);
5043
5246
  else if (s.status === "missing")
5044
- console.log(` ${pc16.yellow("\u2192")} ${s.name.padEnd(16)} ${pc16.yellow("\uBBF8\uC124\uCE58")}`);
5247
+ console.log(` ${pc17.yellow("\u2192")} ${s.name.padEnd(16)} ${pc17.yellow("\uBBF8\uC124\uCE58")}`);
5045
5248
  else if (s.status === "newer")
5046
5249
  console.log(
5047
- ` ${pc16.yellow("!")} ${s.name.padEnd(16)} ${pc16.yellow("\uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804")}` + pc16.dim(
5250
+ ` ${pc17.yellow("!")} ${s.name.padEnd(16)} ${pc17.yellow("\uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804")}` + pc17.dim(
5048
5251
  " \u2014 \uC774 CLI\uAC00 \uC624\uB798\uB3FC \uC61B \uBCF8\uBB38\uC73C\uB85C \uB418\uB3CC\uB9BD\uB2C8\uB2E4(\uD558\uD5A5). \uCD5C\uC2E0 CLI(npx @bstage-sdk/cli@latest)\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
5049
5252
  )
5050
5253
  );
5051
- else console.log(` ${pc16.yellow("\u2192")} ${s.name.padEnd(16)} ${pc16.yellow("\uAD6C\uBC84\uC804/\uC218\uC815\uB428")}`);
5254
+ else console.log(` ${pc17.yellow("\u2192")} ${s.name.padEnd(16)} ${pc17.yellow("\uAD6C\uBC84\uC804/\uC218\uC815\uB428")}`);
5052
5255
  }
5053
5256
  console.log(
5054
- pc16.dim(
5257
+ pc17.dim(
5055
5258
  " \uC544\uB798\uC5D0\uC11C \uC790\uB3D9 \uB3D9\uAE30\uD654\uD569\uB2C8\uB2E4 \u2014 bstage-* \uC2A4\uD0AC\uB9CC \uB36E\uC5B4\uC4F0\uBA70, \uADF8 \uC678 \uC0AC\uC6A9\uC790 \uC2A4\uD0AC\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
5056
5259
  )
5057
5260
  );
@@ -5061,36 +5264,43 @@ function printSkills(r) {
5061
5264
  function printNextSteps(r) {
5062
5265
  const agentsNeedsWork = r.agentsMd.status === "legacy" || r.agentsMd.status === "stale";
5063
5266
  const liquidBroken = (r.liquid?.issues ?? []).some((i) => i.level === "error");
5064
- const hasWork = r.versions.some((v) => v.outdated) || r.migrations.length > 0 || agentsNeedsWork || liquidBroken;
5267
+ const portalBroken = portalNeedsWork(r.portal);
5268
+ const migrationWork = r.versions.some((v) => v.outdated) || r.migrations.length > 0 || agentsNeedsWork || liquidBroken;
5269
+ const hasWork = migrationWork || portalBroken;
5270
+ if (portalBroken) {
5271
+ console.log(pc17.yellow("\uC704 \uD3EC\uD138 \uC9C4\uB2E8 \uD56D\uBAA9\uC744 \uBA3C\uC800 \uD574\uACB0\uD558\uC138\uC694 \u2014 \uAC01 \uD56D\uBAA9\uC758 \uC870\uCE58\uB97C \uB530\uB974\uBA74 \uB429\uB2C8\uB2E4."));
5272
+ }
5065
5273
  if (liquidBroken) {
5066
5274
  console.log(
5067
- pc16.yellow("\uC704 liquid \uAC80\uC99D \uC624\uB958\uB97C \uBA3C\uC800 \uACE0\uCE58\uC138\uC694 \u2014 \uADF8\uB300\uB85C push\uD558\uBA74 \uD3EC\uD138 \uBE4C\uB4DC\uAC00 \uB9C9\uD799\uB2C8\uB2E4.")
5275
+ pc17.yellow("\uC704 liquid \uAC80\uC99D \uC624\uB958\uB97C \uBA3C\uC800 \uACE0\uCE58\uC138\uC694 \u2014 \uADF8\uB300\uB85C push\uD558\uBA74 \uD3EC\uD138 \uBE4C\uB4DC\uAC00 \uB9C9\uD799\uB2C8\uB2E4.")
5068
5276
  );
5069
5277
  }
5070
- if (hasWork) {
5278
+ if (migrationWork) {
5071
5279
  console.log(
5072
- pc16.dim(
5280
+ pc17.dim(
5073
5281
  "\uB2E4\uC74C \uB2E8\uACC4: \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC2A4\uD0AC\uC744 \uC2E4\uD589\uD574 \uC704 \uD56D\uBAA9\uC744 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uB9DE\uCDB0 \uC801\uC6A9\uD558\uC138\uC694.\n \uC0C1\uC138 \uAC00\uC774\uB4DC: SDK \uBB38\uC11C\uC758 MIGRATION.md (\uC704 \uD56D\uBAA9\uBCC4 \uC801\uC6A9 \uC808\uCC28)"
5074
5282
  )
5075
5283
  );
5076
- } else {
5077
- console.log(pc16.green("\u2713 \uCD5C\uC2E0 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4."));
5284
+ } else if (!hasWork) {
5285
+ console.log(pc17.green("\u2713 \uCD5C\uC2E0 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4."));
5078
5286
  if (r.files.some((f) => !f.present)) {
5079
- console.log(pc16.dim(" (\uC704 init \uAE30\uBCF8 \uD30C\uC77C \uCC28\uC774\uB294 \uC120\uD0DD \uC0AC\uD56D\uC785\uB2C8\uB2E4.)"));
5287
+ console.log(pc17.dim(" (\uC704 init \uAE30\uBCF8 \uD30C\uC77C \uCC28\uC774\uB294 \uC120\uD0DD \uC0AC\uD56D\uC785\uB2C8\uB2E4.)"));
5080
5288
  }
5081
5289
  if (r.recommendedDeps.some((d) => !d.declared)) {
5082
- console.log(pc16.dim(" (\uC704 \uAD8C\uC7A5 \uC758\uC874\uC131\uC740 \uBC84\uC804\uACFC \uBB34\uAD00\uD569\uB2C8\uB2E4 \u2014 \uC4F8 \uAC70\uBA74 \uB530\uB85C \uCD94\uAC00\uD558\uC138\uC694.)"));
5290
+ console.log(pc17.dim(" (\uC704 \uAD8C\uC7A5 \uC758\uC874\uC131\uC740 \uBC84\uC804\uACFC \uBB34\uAD00\uD569\uB2C8\uB2E4 \u2014 \uC4F8 \uAC70\uBA74 \uB530\uB85C \uCD94\uAC00\uD558\uC138\uC694.)"));
5083
5291
  }
5084
5292
  }
5085
5293
  console.log("");
5086
5294
  }
5087
5295
  function printReport(r) {
5088
5296
  console.log("");
5089
- console.log(`${pc16.cyan(pc16.bold("bstage doctor"))} ${pc16.dim(`\u2014 ${r.project ?? "(\uC774\uB984 \uC5C6\uC74C)"}`)}`);
5297
+ console.log(`${pc17.cyan(pc17.bold("bstage doctor"))} ${pc17.dim(`\u2014 ${r.project ?? "(\uC774\uB984 \uC5C6\uC74C)"}`)}`);
5090
5298
  console.log("");
5091
5299
  if (!r.isBstageProject) {
5092
- console.log(pc16.yellow("\uC774 \uB514\uB809\uD1A0\uB9AC\uB294 bstage \uD15C\uD50C\uB9BF \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2CC \uAC83 \uAC19\uC2B5\uB2C8\uB2E4."));
5093
- console.log(pc16.dim(" package.json\uC5D0 @bstage-sdk/* \uC758\uC874\uC131\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
5300
+ console.log(pc17.yellow("\uC774 \uB514\uB809\uD1A0\uB9AC\uB294 bstage \uD15C\uD50C\uB9BF \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2CC \uAC83 \uAC19\uC2B5\uB2C8\uB2E4."));
5301
+ console.log(pc17.dim(" package.json\uC5D0 @bstage-sdk/* \uC758\uC874\uC131\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
5302
+ console.log("");
5303
+ printPortal(r.portal);
5094
5304
  return;
5095
5305
  }
5096
5306
  printVersions(r);
@@ -5103,15 +5313,24 @@ function printReport(r) {
5103
5313
  printMigrations(r);
5104
5314
  printAgentsMd(r);
5105
5315
  printSkills(r);
5316
+ printPortal(r.portal);
5106
5317
  printNextSteps(r);
5107
5318
  }
5108
5319
 
5109
5320
  // src/commands/doctor.ts
5110
- async function doctorCommand(options) {
5111
- const root = process.cwd();
5112
- const report2 = await diagnose2(root);
5321
+ async function doctorCommand(options, deps = {}) {
5322
+ const root = deps.cwd ?? process.cwd();
5323
+ const [local, portal] = await Promise.all([
5324
+ diagnose2(root),
5325
+ diagnosePortal(
5326
+ { placement: options.placement },
5327
+ { cwd: root, env: deps.env, fetch: deps.fetch }
5328
+ )
5329
+ ]);
5330
+ const report2 = { ...local, portal };
5331
+ if (portalNeedsWork(portal)) process.exitCode = ExitCode.FAILURE;
5113
5332
  if (options.json) {
5114
- console.log(JSON.stringify(report2, null, 2));
5333
+ printJson(report2);
5115
5334
  return;
5116
5335
  }
5117
5336
  printReport(report2);
@@ -5120,7 +5339,7 @@ async function doctorCommand(options) {
5120
5339
 
5121
5340
  // src/commands/link.ts
5122
5341
  import * as p4 from "@clack/prompts";
5123
- import pc17 from "picocolors";
5342
+ import pc18 from "picocolors";
5124
5343
  var clackSelect = async (message, items) => {
5125
5344
  const options = items.map((i) => ({
5126
5345
  value: i.value,
@@ -5232,15 +5451,15 @@ function printLinked(link, repoLabel, repoFromOrigin, json) {
5232
5451
  return;
5233
5452
  }
5234
5453
  if (repoFromOrigin) {
5235
- console.log(pc17.dim(` git origin(${repoLabel})\uACFC \uC77C\uCE58\uD558\uB294 \uB808\uD3EC\uB97C \uAE30\uBCF8\uAC12\uC73C\uB85C \uC120\uD0DD\uD588\uC2B5\uB2C8\uB2E4.`));
5454
+ console.log(pc18.dim(` git origin(${repoLabel})\uACFC \uC77C\uCE58\uD558\uB294 \uB808\uD3EC\uB97C \uAE30\uBCF8\uAC12\uC73C\uB85C \uC120\uD0DD\uD588\uC2B5\uB2C8\uB2E4.`));
5236
5455
  }
5237
5456
  console.log(
5238
- pc17.green(
5457
+ pc18.green(
5239
5458
  `\u2713 \uC5F0\uACB0\uD588\uC2B5\uB2C8\uB2E4: ${link.organizationId} / ${link.spaceId} / ${repoLabel} [${link.surface}]`
5240
5459
  )
5241
5460
  );
5242
5461
  console.log(
5243
- pc17.dim(
5462
+ pc18.dim(
5244
5463
  " .bstage/project.json \uC5D0 \uC800\uC7A5 (gitignore \uB300\uC0C1). CI\uC5D0\uC11C\uB294 BSTAGE_ORG\xB7BSTAGE_SPACE\xB7BSTAGE_REPO\xB7BSTAGE_SURFACE\xB7BSTAGE_PORTAL_URL \uD658\uACBD\uBCC0\uC218\uB97C \uC4F0\uC138\uC694."
5245
5464
  )
5246
5465
  );
@@ -5295,7 +5514,7 @@ async function linkCommand(options, deps = {}) {
5295
5514
  }
5296
5515
 
5297
5516
  // src/commands/list.ts
5298
- import pc18 from "picocolors";
5517
+ import pc19 from "picocolors";
5299
5518
 
5300
5519
  // src/portal/buildRepo.ts
5301
5520
  function buildMatchesRepo(b, repo) {
@@ -5327,10 +5546,10 @@ function artifactKinds(build) {
5327
5546
  function renderList(placements, builds, repo) {
5328
5547
  const mine = placements.filter((p5) => p5.stageRepoId === repo.id);
5329
5548
  const lines = [];
5330
- lines.push(pc18.bold("\uBC30\uCE58"));
5549
+ lines.push(pc19.bold("\uBC30\uCE58"));
5331
5550
  if (mine.length === 0) {
5332
5551
  lines.push(
5333
- pc18.yellow(
5552
+ pc19.yellow(
5334
5553
  " \uC774 \uB808\uD3EC\uC5D0 \uC5F0\uACB0\uB41C \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. bstage placement create \uB85C \uD398\uC774\uC9C0 \uBC30\uCE58\uB97C \uBA3C\uC800 \uB9CC\uB4DC\uC138\uC694."
5335
5554
  )
5336
5555
  );
@@ -5349,10 +5568,10 @@ function renderList(placements, builds, repo) {
5349
5568
  );
5350
5569
  }
5351
5570
  lines.push("");
5352
- lines.push(pc18.bold("\uCD5C\uADFC \uBE4C\uB4DC"));
5571
+ lines.push(pc19.bold("\uCD5C\uADFC \uBE4C\uB4DC"));
5353
5572
  const recent = builds.filter((b) => buildMatchesRepo(b, repo));
5354
5573
  lines.push(
5355
- recent.length === 0 ? pc18.dim(" \uBE4C\uB4DC \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.") : table([
5574
+ recent.length === 0 ? pc19.dim(" \uBE4C\uB4DC \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.") : table([
5356
5575
  ["\uBE4C\uB4DC", "\uC0C1\uD0DC", "\uC885\uB958", "\uCEE4\uBC0B", "\uC694\uCCAD \uC2DC\uAC01"],
5357
5576
  ...recent.map((b) => [
5358
5577
  b.id,
@@ -5366,7 +5585,7 @@ function renderList(placements, builds, repo) {
5366
5585
  if (mine.length === 0) {
5367
5586
  lines.push("");
5368
5587
  lines.push(
5369
- pc18.yellow(
5588
+ pc19.yellow(
5370
5589
  "\uC774 \uB808\uD3EC\uC5D0 \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uB2E4\uC74C: bstage placement create --template <\uC0B0\uCD9C\uBB3C \uC774\uB984> [--path /\uACBD\uB85C] \u2192 bstage deploy. \uC704\uC82F(\uC2AC\uB86F) \uBC30\uCE58\uB294 \uD3EC\uD138 \uD654\uBA74(\uC2A4\uD14C\uC774\uC9C0 > \uD398\uC774\uC9C0 > \uC0C8 \uD398\uC774\uC9C0)\uC5D0\uC11C \uB9CC\uB4ED\uB2C8\uB2E4. (bstage-deploy \uC2A4\uD0AC \uCC38\uC870)"
5371
5590
  )
5372
5591
  );
@@ -5392,12 +5611,12 @@ async function listCommand(options, deps = {}) {
5392
5611
  printJson({ link, placements: mine, builds: myBuilds });
5393
5612
  return;
5394
5613
  }
5395
- out(pc18.dim(`${link.organizationId} / ${link.spaceId} [${link.surface}]`));
5614
+ out(pc19.dim(`${link.organizationId} / ${link.spaceId} [${link.surface}]`));
5396
5615
  out(renderList(placements, builds, repo));
5397
5616
  }
5398
5617
 
5399
5618
  // src/commands/logs.ts
5400
- import pc19 from "picocolors";
5619
+ import pc20 from "picocolors";
5401
5620
  function statusLine(build) {
5402
5621
  return `[bstage] \uBE4C\uB4DC ${build.id} \xB7 ${build.status}${build.failureReason ? ` \xB7 ${build.failureReason}` : ""}`;
5403
5622
  }
@@ -5411,7 +5630,7 @@ async function latestBuildId(ctx) {
5411
5630
  return latest.id;
5412
5631
  }
5413
5632
  function logSink(json) {
5414
- return json ? (delta) => void process.stderr.write(pc19.dim(delta)) : (delta) => void process.stdout.write(delta);
5633
+ return json ? (delta) => void process.stderr.write(pc20.dim(delta)) : (delta) => void process.stdout.write(delta);
5415
5634
  }
5416
5635
  async function logsCommand(buildId, options, deps = {}) {
5417
5636
  const out = deps.out ?? ((s) => void process.stdout.write(s));
@@ -5435,17 +5654,17 @@ async function report(client, org, space, id, build, options, out, following) {
5435
5654
  return;
5436
5655
  }
5437
5656
  if (following) {
5438
- console.error(pc19.dim(`
5657
+ console.error(pc20.dim(`
5439
5658
  ${statusLine(build)}`));
5440
5659
  return;
5441
5660
  }
5442
5661
  const log3 = await client.getBuildLog(org, space, id);
5443
5662
  out(log3.endsWith("\n") ? log3 : log3 + "\n");
5444
- console.error(pc19.dim(statusLine(build)));
5663
+ console.error(pc20.dim(statusLine(build)));
5445
5664
  }
5446
5665
 
5447
5666
  // src/commands/placement.ts
5448
- import pc20 from "picocolors";
5667
+ import pc21 from "picocolors";
5449
5668
 
5450
5669
  // src/portal/pagePlacement.ts
5451
5670
  function normalizePagePath(raw) {
@@ -5516,7 +5735,7 @@ async function ensureBuildWithArtifact(ctx, repo, template, options, deps) {
5516
5735
  const latest = options.build ? void 0 : latestSucceeded(await ctx.client.listBuilds(org, space, RECENT_BUILDS), repo);
5517
5736
  const found = latest && resolvePageArtifact(latest, template, surface);
5518
5737
  if (latest && found) return { build: latest, artifact: found };
5519
- if (!options.json) console.error(pc20.dim(`[bstage] ${buildReason(latest, options)}`));
5738
+ if (!options.json) console.error(pc21.dim(`[bstage] ${buildReason(latest, options)}`));
5520
5739
  if (!options.skipGitCheck) await precheckGit(deps, repo.defaultBranch);
5521
5740
  const created = await createAndAnnounceBuild(ctx, options.json);
5522
5741
  const done = await waitForCompletedBuild(ctx, deps, created, options.json);
@@ -5547,9 +5766,9 @@ function reportExisting(owner, resolved, repoId, options, out) {
5547
5766
  return;
5548
5767
  }
5549
5768
  out(
5550
- `${pc20.green("\u2713")} ${label} \uC5D0 \uC774 \uB808\uD3EC\uC758 '${resolved.artifact.name}' \uBC30\uCE58\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4 (${owner.id}).`
5769
+ `${pc21.green("\u2713")} ${label} \uC5D0 \uC774 \uB808\uD3EC\uC758 '${resolved.artifact.name}' \uBC30\uCE58\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4 (${owner.id}).`
5551
5770
  );
5552
- out(pc20.dim(` \uB2E4\uC74C: ${nextCommand(label)}`));
5771
+ out(pc21.dim(` \uB2E4\uC74C: ${nextCommand(label)}`));
5553
5772
  return;
5554
5773
  }
5555
5774
  const who = `\uBC30\uCE58 ${owner.id}, \uC0B0\uCD9C\uBB3C ${owner.artifact ?? "-"}${owner.stageRepoId === repoId ? "" : ", \uB2E4\uB978 \uB808\uD3EC"}`;
@@ -5623,9 +5842,9 @@ function reportCreated(created, resolved, options, out) {
5623
5842
  return;
5624
5843
  }
5625
5844
  out(
5626
- `${pc20.green("\u2713")} \uBC30\uCE58\uB97C \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: ${label} \u2190 ${resolved.artifact.name} (${created.id}, \uBE4C\uB4DC ${resolved.build.id} \xB7 ${shortSha(resolved.build.commitSha)})`
5845
+ `${pc21.green("\u2713")} \uBC30\uCE58\uB97C \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: ${label} \u2190 ${resolved.artifact.name} (${created.id}, \uBE4C\uB4DC ${resolved.build.id} \xB7 ${shortSha(resolved.build.commitSha)})`
5627
5846
  );
5628
- out(pc20.dim(` \uC544\uC9C1 \uB77C\uC774\uBE0C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uB2E4\uC74C: ${nextCommand(label)}`));
5847
+ out(pc21.dim(` \uC544\uC9C1 \uB77C\uC774\uBE0C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uB2E4\uC74C: ${nextCommand(label)}`));
5629
5848
  }
5630
5849
  async function placementCreateCommand(options, deps = {}) {
5631
5850
  if (options.json && !options.yes) {
@@ -5678,7 +5897,7 @@ async function placementCreateCommand(options, deps = {}) {
5678
5897
 
5679
5898
  // src/commands/login.ts
5680
5899
  import { hostname as osHostname } from "os";
5681
- import pc21 from "picocolors";
5900
+ import pc22 from "picocolors";
5682
5901
 
5683
5902
  // src/portal/openBrowser.ts
5684
5903
  import { execFile as execFile2 } from "child_process";
@@ -5746,7 +5965,7 @@ async function loginWithToken(portalUrl, token, options, deps, env2) {
5746
5965
  return;
5747
5966
  }
5748
5967
  console.log(
5749
- pc21.green(`\u2713 ${portalUrl} \uC5D0 ${me.user.email} \uB85C \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4 (\uC870\uC9C1 ${organizationId}).`)
5968
+ pc22.green(`\u2713 ${portalUrl} \uC5D0 ${me.user.email} \uB85C \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4 (\uC870\uC9C1 ${organizationId}).`)
5750
5969
  );
5751
5970
  }
5752
5971
  function nextIntervalOnSlowDown(interval, retryAfterSec) {
@@ -5757,11 +5976,11 @@ function printDeviceCodePrompt(userCode, verificationUriComplete, expiresIn) {
5757
5976
  console.log("");
5758
5977
  console.log(` \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC544\uB798 \uCF54\uB4DC\uB97C \uD655\uC778\uD558\uACE0 \uC2B9\uC778\uD558\uC138\uC694.`);
5759
5978
  console.log("");
5760
- console.log(` \uCF54\uB4DC ${pc21.bold(userCode)}`);
5761
- console.log(` \uC8FC\uC18C ${pc21.underline(verificationUriComplete)}`);
5979
+ console.log(` \uCF54\uB4DC ${pc22.bold(userCode)}`);
5980
+ console.log(` \uC8FC\uC18C ${pc22.underline(verificationUriComplete)}`);
5762
5981
  console.log("");
5763
5982
  console.log(
5764
- pc21.dim(
5983
+ pc22.dim(
5765
5984
  ` \uD130\uBBF8\uB110\uC758 \uCF54\uB4DC\uC640 \uBE0C\uB77C\uC6B0\uC800\uC758 \uCF54\uB4DC\uAC00 \uAC19\uC740\uC9C0 \uAF2D \uD655\uC778\uD558\uC138\uC694. ${Math.round(expiresIn / 60)}\uBD84 \uC548\uC5D0 \uC2B9\uC778\uB418\uC9C0 \uC54A\uC73C\uBA74 \uB9CC\uB8CC\uB429\uB2C8\uB2E4.`
5766
5985
  )
5767
5986
  );
@@ -5802,7 +6021,7 @@ async function openVerificationUri(portalUrl, verificationUriComplete, options,
5802
6021
  if (!sameOrigin(portalUrl, verificationUriComplete)) {
5803
6022
  if (!options.json) {
5804
6023
  console.log(
5805
- pc21.yellow(
6024
+ pc22.yellow(
5806
6025
  " \uC2B9\uC778 \uC8FC\uC18C\uAC00 \uD3EC\uD138\uACFC \uB2E4\uB978 \uC0AC\uC774\uD2B8\uC785\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 \uC8FC\uC18C\uB97C \uD655\uC778\uD55C \uB4A4 \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."
5807
6026
  )
5808
6027
  );
@@ -5811,7 +6030,7 @@ async function openVerificationUri(portalUrl, verificationUriComplete, options,
5811
6030
  }
5812
6031
  const opened = await (deps.openBrowser ?? openBrowser)(verificationUriComplete);
5813
6032
  if (!opened && !options.json) {
5814
- console.log(pc21.dim(" \uBE0C\uB77C\uC6B0\uC800\uB97C \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."));
6033
+ console.log(pc22.dim(" \uBE0C\uB77C\uC6B0\uC800\uB97C \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."));
5815
6034
  }
5816
6035
  }
5817
6036
  function sameOrigin(a, b) {
@@ -5876,13 +6095,13 @@ function reportIssued(portalUrl, issued, organizationId, json) {
5876
6095
  });
5877
6096
  return;
5878
6097
  }
5879
- console.log(pc21.green(`\u2713 ${portalUrl} \uC5D0 \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4.`));
6098
+ console.log(pc22.green(`\u2713 ${portalUrl} \uC5D0 \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4.`));
5880
6099
  console.log(
5881
- pc21.dim(
6100
+ pc22.dim(
5882
6101
  ` \uC870\uC9C1 ${orgLabel(organizationId ?? UNKNOWN_ORG)} \xB7 \uD1A0\uD070 ${issued.prefix}\u2026 \xB7 \uB4F1\uAE09 ${issued.permission} \xB7 ${scopeLabel(issued.allSpaces, issued.spaceIds)} \xB7 \uB9CC\uB8CC ${issued.expiresAt.slice(0, 10)}`
5883
6102
  )
5884
6103
  );
5885
- console.log(pc21.dim(" \uB2E4\uC74C: \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC\uC5D0\uC11C bstage link"));
6104
+ console.log(pc22.dim(" \uB2E4\uC74C: \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC\uC5D0\uC11C bstage link"));
5886
6105
  }
5887
6106
  async function loginCommand(options, deps = {}) {
5888
6107
  const env2 = deps.env ?? process.env;
@@ -5899,7 +6118,7 @@ async function loginCommand(options, deps = {}) {
5899
6118
  }
5900
6119
 
5901
6120
  // src/commands/logout.ts
5902
- import pc22 from "picocolors";
6121
+ import pc23 from "picocolors";
5903
6122
  async function logoutCommand(options, deps = {}) {
5904
6123
  const cwd = deps.cwd ?? process.cwd();
5905
6124
  const env2 = deps.env ?? process.env;
@@ -5913,16 +6132,16 @@ async function logoutCommand(options, deps = {}) {
5913
6132
  const removed = await deleteCredential(portalUrl, options.org, env2);
5914
6133
  if (removed.length === 0) {
5915
6134
  const scope = options.org ? `\uC870\uC9C1 ${options.org} \uC758 ` : "";
5916
- console.log(pc22.yellow(`${portalUrl} \uC5D0 \uC800\uC7A5\uB41C ${scope}\uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.`));
6135
+ console.log(pc23.yellow(`${portalUrl} \uC5D0 \uC800\uC7A5\uB41C ${scope}\uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.`));
5917
6136
  } else {
5918
6137
  const orgs = removed.map(orgLabel).join(", ");
5919
- console.log(pc22.green(`\u2713 ${portalUrl} \uC790\uACA9\uC99D\uBA85\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC870\uC9C1 ${orgs}`));
6138
+ console.log(pc23.green(`\u2713 ${portalUrl} \uC790\uACA9\uC99D\uBA85\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC870\uC9C1 ${orgs}`));
5920
6139
  }
5921
- console.log(pc22.dim(" \uD3EC\uD138 \uD654\uBA74\uC5D0\uC11C \uD1A0\uD070 \uC790\uCCB4\uB97C \uD3D0\uAE30\uD558\uBA74 \uB2E4\uB978 \uAE30\uAE30\uC5D0\uC11C\uB3C4 \uBB34\uD6A8\uAC00 \uB429\uB2C8\uB2E4."));
6140
+ console.log(pc23.dim(" \uD3EC\uD138 \uD654\uBA74\uC5D0\uC11C \uD1A0\uD070 \uC790\uCCB4\uB97C \uD3D0\uAE30\uD558\uBA74 \uB2E4\uB978 \uAE30\uAE30\uC5D0\uC11C\uB3C4 \uBB34\uD6A8\uAC00 \uB429\uB2C8\uB2E4."));
5922
6141
  }
5923
6142
 
5924
6143
  // src/commands/publish.ts
5925
- import pc23 from "picocolors";
6144
+ import pc24 from "picocolors";
5926
6145
  function parseOnOff(v) {
5927
6146
  const s = v.toLowerCase();
5928
6147
  if (s === "on") return true;
@@ -5961,13 +6180,13 @@ async function togglePlacement(ctx, p5, enabled) {
5961
6180
  }
5962
6181
  function printResults2(results, enabled, out) {
5963
6182
  for (const r of results) {
5964
- const mark = r.status === "failed" ? pc23.red("\u2717") : r.status === "conflict" ? pc23.yellow("!") : pc23.green("\u2713");
6183
+ const mark = r.status === "failed" ? pc24.red("\u2717") : r.status === "conflict" ? pc24.yellow("!") : pc24.green("\u2713");
5965
6184
  const stateLabel = r.status === "unchanged" ? "\uBCC0\uACBD \uC5C6\uC74C" : `\uAC8C\uC2DC ${r.enabled ? "on" : "off"}`;
5966
- const suffix = r.message && r.status !== "unchanged" ? pc23.dim(` ${r.message}`) : "";
6185
+ const suffix = r.message && r.status !== "unchanged" ? pc24.dim(` ${r.message}`) : "";
5967
6186
  out(`${mark} ${r.label} ${stateLabel}${suffix}`);
5968
6187
  }
5969
6188
  if (!enabled) {
5970
- out(pc23.dim(" \uB77C\uC774\uBE0C \uBC84\uC804 \uD3EC\uC778\uD130\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uCF1C\uBA74 \uAC19\uC740 \uBE4C\uB4DC\uAC00 \uC989\uC2DC \uC11C\uBE59\uB429\uB2C8\uB2E4."));
6189
+ out(pc24.dim(" \uB77C\uC774\uBE0C \uBC84\uC804 \uD3EC\uC778\uD130\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uCF1C\uBA74 \uAC19\uC740 \uBE4C\uB4DC\uAC00 \uC989\uC2DC \uC11C\uBE59\uB429\uB2C8\uB2E4."));
5971
6190
  }
5972
6191
  }
5973
6192
  function reportOutcome2(results, options, enabled, out) {
@@ -6007,7 +6226,7 @@ async function publishCommand(state, options, deps = {}) {
6007
6226
  }
6008
6227
 
6009
6228
  // src/commands/rollback.ts
6010
- import pc24 from "picocolors";
6229
+ import pc25 from "picocolors";
6011
6230
  function pickRollbackTarget(builds, repo, currentLive) {
6012
6231
  const ok = builds.filter((b) => buildMatchesRepo(b, repo) && b.status === "SUCCEEDED").sort((a, b) => a.requestedAt < b.requestedAt ? 1 : -1);
6013
6232
  if (!currentLive) return ok[0] ?? null;
@@ -6092,16 +6311,16 @@ async function rollbackCommand(buildId, options, deps = {}) {
6092
6311
  reportOutcome(results, options, out);
6093
6312
  if (!options.json) {
6094
6313
  out(
6095
- pc24.dim(" \uB418\uB3CC\uB9B0 \uB4A4\uC5D0\uB3C4 \uCD5C\uC2E0 \uBE4C\uB4DC\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 \u2014 bstage deploy \uB85C \uB2E4\uC2DC \uC62C\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.")
6314
+ pc25.dim(" \uB418\uB3CC\uB9B0 \uB4A4\uC5D0\uB3C4 \uCD5C\uC2E0 \uBE4C\uB4DC\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 \u2014 bstage deploy \uB85C \uB2E4\uC2DC \uC62C\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.")
6096
6315
  );
6097
6316
  }
6098
6317
  }
6099
6318
 
6100
6319
  // src/commands/skills.ts
6101
- import pc25 from "picocolors";
6320
+ import pc26 from "picocolors";
6102
6321
  async function skillsInstallCommand(options) {
6103
6322
  console.warn(
6104
- pc25.yellow(
6323
+ pc26.yellow(
6105
6324
  "bstage skills install\uC740 bstage ai install\uB85C \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC74C \uB9B4\uB9AC\uC988\uC5D0\uC11C \uC81C\uAC70\uB429\uB2C8\uB2E4."
6106
6325
  )
6107
6326
  );
@@ -6111,7 +6330,7 @@ async function skillsInstallCommand(options) {
6111
6330
  // src/commands/docs.ts
6112
6331
  import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
6113
6332
  import { join as join16 } from "path";
6114
- import pc26 from "picocolors";
6333
+ import pc27 from "picocolors";
6115
6334
  var DOC_ORDER = [
6116
6335
  ["GETTING_STARTED.md", "\uBE60\uB978 \uC2DC\uC791 \uAC00\uC774\uB4DC"],
6117
6336
  ["API_REFERENCE.md", "createTemplate, hooks, BstageClient, PlatformBridge API"],
@@ -6131,10 +6350,10 @@ var CORE_DOCS_SEGMENTS = ["node_modules", "@bstage-sdk", "core", "docs"];
6131
6350
  async function docsCommand() {
6132
6351
  const docsDir = join16(process.cwd(), ...CORE_DOCS_SEGMENTS);
6133
6352
  if (!existsSync8(docsDir)) {
6134
- console.log(pc26.yellow("SDK \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
6135
- console.log(pc26.dim(" @bstage-sdk/core\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 (npm install \uD6C4 \uC7AC\uC2DC\uB3C4)."));
6353
+ console.log(pc27.yellow("SDK \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
6354
+ console.log(pc27.dim(" @bstage-sdk/core\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 (npm install \uD6C4 \uC7AC\uC2DC\uB3C4)."));
6136
6355
  console.log(
6137
- pc26.dim(
6356
+ pc27.dim(
6138
6357
  " SDK \uC758\uC874\uC774 \uC5C6\uB294 \uB808\uD3EC\uC5D0\uB294 \uC774 \uACBD\uB85C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 liquid \uADDC\uC57D\xB7\uB370\uC774\uD130\uB294 bstage-liquid \uC2A4\uD0AC\uC744 \uBCF4\uC138\uC694."
6139
6358
  )
6140
6359
  );
@@ -6146,24 +6365,24 @@ async function docsCommand() {
6146
6365
  const known = new Set(DOC_ORDER.map(([f]) => f));
6147
6366
  const extras = [...present].filter((f) => !known.has(f)).sort();
6148
6367
  console.log("");
6149
- console.log(pc26.bold("bstage SDK \uBB38\uC11C"));
6150
- console.log(pc26.dim(` ${docsDir}`));
6368
+ console.log(pc27.bold("bstage SDK \uBB38\uC11C"));
6369
+ console.log(pc27.dim(` ${docsDir}`));
6151
6370
  console.log("");
6152
6371
  for (const [file3, desc] of ordered) {
6153
- console.log(` ${pc26.cyan(file3.padEnd(22))} ${pc26.dim(desc)}`);
6372
+ console.log(` ${pc27.cyan(file3.padEnd(22))} ${pc27.dim(desc)}`);
6154
6373
  }
6155
6374
  for (const file3 of extras) {
6156
- console.log(` ${pc26.cyan(file3.padEnd(22))}`);
6375
+ console.log(` ${pc27.cyan(file3.padEnd(22))}`);
6157
6376
  }
6158
6377
  console.log("");
6159
6378
  console.log(
6160
- pc26.dim("\uD30C\uC77C\uC744 \uC5F4\uC5B4 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uD655\uC778\uD558\uC138\uC694. \uCEE4\uB9E8\uB4DC \uB3C4\uC6C0\uB9D0\uC740 `bstage <command> --help`.")
6379
+ pc27.dim("\uD30C\uC77C\uC744 \uC5F4\uC5B4 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uD655\uC778\uD558\uC138\uC694. \uCEE4\uB9E8\uB4DC \uB3C4\uC6C0\uB9D0\uC740 `bstage <command> --help`.")
6161
6380
  );
6162
6381
  console.log("");
6163
6382
  }
6164
6383
 
6165
6384
  // src/commands/whoami.ts
6166
- import pc27 from "picocolors";
6385
+ import pc28 from "picocolors";
6167
6386
  function jsonEntry(c, active) {
6168
6387
  return {
6169
6388
  organizationId: c.organizationId,
@@ -6177,21 +6396,21 @@ function jsonEntry(c, active) {
6177
6396
  }
6178
6397
  function printCredentials(stored, activeOrg) {
6179
6398
  if (stored.length === 0) return;
6180
- console.log(pc27.dim("\uC800\uC7A5\uB41C \uD1A0\uD070"));
6399
+ console.log(pc28.dim("\uC800\uC7A5\uB41C \uD1A0\uD070"));
6181
6400
  const rows = stored.map((c) => [
6182
6401
  ` \uC870\uC9C1 ${orgLabel(c.organizationId)}`,
6183
6402
  `\uB4F1\uAE09 ${c.permission ?? "-"}`,
6184
6403
  scopeLabel(c.allSpaces, c.spaceIds),
6185
6404
  `\uB9CC\uB8CC ${c.expiresAt ? c.expiresAt.slice(0, 10) : "-"}`,
6186
- c.organizationId === activeOrg ? pc27.dim("(\uC0AC\uC6A9 \uC911)") : ""
6405
+ c.organizationId === activeOrg ? pc28.dim("(\uC0AC\uC6A9 \uC911)") : ""
6187
6406
  ]);
6188
6407
  console.log(table(rows));
6189
6408
  }
6190
6409
  function printMe(me, portalUrl) {
6191
- console.log(`${pc27.bold(me.user.email)} ${pc27.dim(portalUrl)}`);
6410
+ console.log(`${pc28.bold(me.user.email)} ${pc28.dim(portalUrl)}`);
6192
6411
  for (const m of me.memberships) {
6193
6412
  const stages = Object.entries(m.stageRoles ?? {}).map(([s, r]) => `${s}:${r}`).join(", ");
6194
- console.log(` \uC870\uC9C1 ${m.organizationId} ${m.organizationRole ?? ""} ${pc27.dim(stages)}`);
6413
+ console.log(` \uC870\uC9C1 ${m.organizationId} ${m.organizationRole ?? ""} ${pc28.dim(stages)}`);
6195
6414
  }
6196
6415
  }
6197
6416
  async function whoamiCommand(options, deps = {}) {
@@ -6247,10 +6466,10 @@ function reportStoredOnly(portalUrl, stored, json) {
6247
6466
  });
6248
6467
  return;
6249
6468
  }
6250
- console.log(pc27.dim(portalUrl));
6469
+ console.log(pc28.dim(portalUrl));
6251
6470
  printCredentials(stored);
6252
6471
  console.log(
6253
- pc27.yellow(" \uC5EC\uB7EC \uC870\uC9C1\uC758 \uD1A0\uD070\uC774 \uC788\uC2B5\uB2C8\uB2E4 \u2014 --org <id> \uB85C \uC870\uC9C1\uC744 \uC9C0\uC815\uD558\uBA74 \uACC4\uC815 \uC815\uBCF4\uB3C4 \uBD05\uB2C8\uB2E4.")
6472
+ pc28.yellow(" \uC5EC\uB7EC \uC870\uC9C1\uC758 \uD1A0\uD070\uC774 \uC788\uC2B5\uB2C8\uB2E4 \u2014 --org <id> \uB85C \uC870\uC9C1\uC744 \uC9C0\uC815\uD558\uBA74 \uACC4\uC815 \uC815\uBCF4\uB3C4 \uBD05\uB2C8\uB2E4.")
6254
6473
  );
6255
6474
  }
6256
6475
 
@@ -6270,8 +6489,11 @@ program.command("build").description(
6270
6489
  ).option("--json", "\uAC80\uC99D \uACB0\uACFC\xB7\uC0B0\uCD9C\uBB3C \uC694\uC57D\uC744 JSON\uC73C\uB85C \uCD9C\uB825 (liquid\xB7\uD63C\uD569 \uB808\uD3EC)").action((options) => buildCommand(options));
6271
6490
  program.command("docs").description("\uC124\uCE58\uB41C SDK \uBB38\uC11C \uBAA9\uB85D\xB7\uACBD\uB85C \uCD9C\uB825").action(docsCommand);
6272
6491
  program.command("doctor").description(
6273
- "SDK \uBC84\uC804\xB7\uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uB4DC\uB9AC\uD504\uD2B8 \uC9C4\uB2E8 (\uC9C4\uB2E8 + SDK \uC18C\uC720 \uC2A4\uD0AC \uC790\uB3D9 \uB3D9\uAE30\uD654; package.json\xB7\uD6C5\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C)"
6274
- ).option("--json", "\uAD6C\uC870\uD654 \uCD9C\uB825 (\uC2A4\uD0AC\xB7CI\uC6A9)").action(doctorCommand);
6492
+ "SDK \uBC84\uC804\xB7\uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uB4DC\uB9AC\uD504\uD2B8 + \uD3EC\uD138 \uBC30\uCE58 \uC9C4\uB2E8 (\uC9C4\uB2E8 + SDK \uC18C\uC720 \uC2A4\uD0AC \uC790\uB3D9 \uB3D9\uAE30\uD654; package.json\xB7\uD6C5\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C)"
6493
+ ).option("--json", "\uAD6C\uC870\uD654 \uCD9C\uB825 (\uC2A4\uD0AC\xB7CI\uC6A9)").option(
6494
+ "--placement <target>",
6495
+ "\uD3EC\uD138 \uC9C4\uB2E8\uC744 \uBC30\uCE58 \uD558\uB098\uB85C \uC881\uD798 (id\xB7\uACBD\uB85C\xB7\uC2AC\uB86F id). \uB9C1\uD06C\xB7\uB85C\uADF8\uC778\uC774 \uC5C6\uC73C\uBA74 \uC885\uB8CC \uCF54\uB4DC 2\xB73"
6496
+ ).action((o) => runCommand(() => doctorCommand(o)));
6275
6497
  program.command("dev").description("\uC778\uC99D \uD504\uB85D\uC2DC \uD3EC\uD568 \uB85C\uCEEC \uAC1C\uBC1C \uC11C\uBC84 (liquid \uB808\uD3EC\uB294 liquidjs \uD504\uB9AC\uBDF0)").option("-p, --port <port>", "Dev server port", "5173").option(
6276
6498
  "--phase <phase>",
6277
6499
  "Target phase (dev, qa, real, sandbox). \uC0DD\uB7B5 \uC2DC .env\uC758 VITE_BSTAGE_PHASE, \uADF8\uAC83\uB3C4 \uC5C6\uC73C\uBA74 sandbox"
@@ -6326,6 +6548,8 @@ program.addHelpText(
6326
6548
  $ bstage dev \uB85C\uCEEC \uAC1C\uBC1C \uC11C\uBC84 (\uC778\uC99D \uD504\uB85D\uC2DC \xB7 liquid \uB808\uD3EC\uB294 liquidjs \uD504\uB9AC\uBDF0)
6327
6549
  $ bstage build IIFE \uBC88\uB4E4 \uBE4C\uB4DC (dist/{\uACBD\uB85C} \xB7 dist/{\uC2AC\uB86F})
6328
6550
  $ bstage doctor SDK \uBC84\uC804\xB7\uB4DC\uB9AC\uD504\uD2B8 \uC9C4\uB2E8
6551
+ $ bstage doctor --placement /me
6552
+ \uBC30\uCE58 \uD558\uB098\uB9CC \uD3EC\uD138 \uC9C4\uB2E8 (\uAC8C\uC2DC\xB7\uBE4C\uB4DC\xB7\uC571 \uD0A4 \uBB38\uC81C\uC640 \uC870\uCE58)
6329
6553
  $ bstage ai install \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC\xB7AGENTS.md \uC124\uCE58/\uCD5C\uC2E0\uD654 (+ \uC2DC\uD06C\uB9BF \uAC00\uB4DC)
6330
6554
  $ bstage ai doctor \uC5D0\uC774\uC804\uD2B8 \uC790\uC0B0 \uCD5C\uC2E0 \uC5EC\uBD80 \uC9C4\uB2E8
6331
6555
  $ bstage i18n pull \uD50C\uB7AB\uD3FC \uBC88\uC5ED \uBC1B\uAE30 + \uD0C0\uC785 \uC0DD\uC131
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bstage-sdk/cli",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "bstage SDK CLI — build b.stage templates",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -32,14 +32,14 @@
32
32
  "liquidjs": "^10.24.0",
33
33
  "picocolors": "^1.1.1",
34
34
  "vite": "^7.0.0",
35
- "@bstage-sdk/ai-toolkit": "0.8.3",
36
- "@bstage-sdk/core": "0.8.3"
35
+ "@bstage-sdk/ai-toolkit": "0.8.5",
36
+ "@bstage-sdk/core": "0.8.5"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^25.5.0",
40
40
  "tsup": "^8.0.0",
41
41
  "typescript": "^5.5.0",
42
- "@bstage-sdk/design": "0.8.3"
42
+ "@bstage-sdk/design": "0.8.5"
43
43
  },
44
44
  "license": "MIT",
45
45
  "scripts": {