@things-factory/board-ai 10.0.0-beta.108
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/PLAN-styling-tools.md +1253 -0
- package/client/components/board-ai-chat.test.ts +149 -0
- package/client/components/board-ai-chat.ts +2574 -0
- package/client/components/chat-echo-dedup.test.ts +116 -0
- package/client/components/chat-echo-dedup.ts +89 -0
- package/client/components/chat-input-builder.ts +47 -0
- package/client/components/default-catalog-entries.test.ts +59 -0
- package/client/components/default-catalog-entries.ts +100 -0
- package/client/components/default-slash-templates.test.ts +55 -0
- package/client/components/default-slash-templates.ts +129 -0
- package/client/components/markdown.test.ts +518 -0
- package/client/components/markdown.ts +508 -0
- package/client/components/mention-popup-helpers.ts +433 -0
- package/client/components/mention-popup.test.ts +588 -0
- package/client/components/mention-popup.ts +238 -0
- package/client/index.ts +11 -0
- package/client/tsconfig.json +13 -0
- package/client/utils/board-edit-patch.ts +374 -0
- package/config/config.development.js +43 -0
- package/config/config.production.js +15 -0
- package/dist-client/client/components/board-ai-chat.d.ts +277 -0
- package/dist-client/client/components/board-ai-chat.js +2444 -0
- package/dist-client/client/components/board-ai-chat.js.map +1 -0
- package/dist-client/client/components/board-ai-chat.test.d.ts +1 -0
- package/dist-client/client/components/board-ai-chat.test.js +138 -0
- package/dist-client/client/components/board-ai-chat.test.js.map +1 -0
- package/dist-client/client/components/chat-echo-dedup.d.ts +45 -0
- package/dist-client/client/components/chat-echo-dedup.js +58 -0
- package/dist-client/client/components/chat-echo-dedup.js.map +1 -0
- package/dist-client/client/components/chat-echo-dedup.test.d.ts +1 -0
- package/dist-client/client/components/chat-echo-dedup.test.js +101 -0
- package/dist-client/client/components/chat-echo-dedup.test.js.map +1 -0
- package/dist-client/client/components/chat-input-builder.d.ts +39 -0
- package/dist-client/client/components/chat-input-builder.js +26 -0
- package/dist-client/client/components/chat-input-builder.js.map +1 -0
- package/dist-client/client/components/default-catalog-entries.d.ts +15 -0
- package/dist-client/client/components/default-catalog-entries.js +86 -0
- package/dist-client/client/components/default-catalog-entries.js.map +1 -0
- package/dist-client/client/components/default-catalog-entries.test.d.ts +1 -0
- package/dist-client/client/components/default-catalog-entries.test.js +52 -0
- package/dist-client/client/components/default-catalog-entries.test.js.map +1 -0
- package/dist-client/client/components/default-slash-templates.d.ts +17 -0
- package/dist-client/client/components/default-slash-templates.js +113 -0
- package/dist-client/client/components/default-slash-templates.js.map +1 -0
- package/dist-client/client/components/default-slash-templates.test.d.ts +1 -0
- package/dist-client/client/components/default-slash-templates.test.js +51 -0
- package/dist-client/client/components/default-slash-templates.test.js.map +1 -0
- package/dist-client/client/components/markdown.d.ts +60 -0
- package/dist-client/client/components/markdown.js +422 -0
- package/dist-client/client/components/markdown.js.map +1 -0
- package/dist-client/client/components/markdown.test.d.ts +1 -0
- package/dist-client/client/components/markdown.test.js +418 -0
- package/dist-client/client/components/markdown.test.js.map +1 -0
- package/dist-client/client/components/mention-popup-helpers.d.ts +165 -0
- package/dist-client/client/components/mention-popup-helpers.js +330 -0
- package/dist-client/client/components/mention-popup-helpers.js.map +1 -0
- package/dist-client/client/components/mention-popup.d.ts +35 -0
- package/dist-client/client/components/mention-popup.js +223 -0
- package/dist-client/client/components/mention-popup.js.map +1 -0
- package/dist-client/client/components/mention-popup.test.d.ts +1 -0
- package/dist-client/client/components/mention-popup.test.js +474 -0
- package/dist-client/client/components/mention-popup.test.js.map +1 -0
- package/dist-client/client/index.d.ts +11 -0
- package/dist-client/client/index.js +12 -0
- package/dist-client/client/index.js.map +1 -0
- package/dist-client/client/utils/board-edit-patch.d.ts +157 -0
- package/dist-client/client/utils/board-edit-patch.js +284 -0
- package/dist-client/client/utils/board-edit-patch.js.map +1 -0
- package/dist-client/server/service/agentic-loop.d.ts +87 -0
- package/dist-client/server/service/agentic-loop.js +276 -0
- package/dist-client/server/service/agentic-loop.js.map +1 -0
- package/dist-client/server/service/assistant.d.ts +84 -0
- package/dist-client/server/service/assistant.js +2220 -0
- package/dist-client/server/service/assistant.js.map +1 -0
- package/dist-client/server/service/catalog-resolver.d.ts +18 -0
- package/dist-client/server/service/catalog-resolver.js +93 -0
- package/dist-client/server/service/catalog-resolver.js.map +1 -0
- package/dist-client/server/service/component-tree.d.ts +68 -0
- package/dist-client/server/service/component-tree.js +68 -0
- package/dist-client/server/service/component-tree.js.map +1 -0
- package/dist-client/server/service/mention-resolver.d.ts +96 -0
- package/dist-client/server/service/mention-resolver.js +172 -0
- package/dist-client/server/service/mention-resolver.js.map +1 -0
- package/dist-client/server/service/prefab-registry.d.ts +73 -0
- package/dist-client/server/service/prefab-registry.js +252 -0
- package/dist-client/server/service/prefab-registry.js.map +1 -0
- package/dist-client/server/service/styling/clear-tools.d.ts +15 -0
- package/dist-client/server/service/styling/clear-tools.js +50 -0
- package/dist-client/server/service/styling/clear-tools.js.map +1 -0
- package/dist-client/server/service/styling/color-utils.d.ts +43 -0
- package/dist-client/server/service/styling/color-utils.js +205 -0
- package/dist-client/server/service/styling/color-utils.js.map +1 -0
- package/dist-client/server/service/styling/copy-tools.d.ts +27 -0
- package/dist-client/server/service/styling/copy-tools.js +78 -0
- package/dist-client/server/service/styling/copy-tools.js.map +1 -0
- package/dist-client/server/service/styling/effect-tools.d.ts +45 -0
- package/dist-client/server/service/styling/effect-tools.js +85 -0
- package/dist-client/server/service/styling/effect-tools.js.map +1 -0
- package/dist-client/server/service/styling/fill-tools.d.ts +60 -0
- package/dist-client/server/service/styling/fill-tools.js +226 -0
- package/dist-client/server/service/styling/fill-tools.js.map +1 -0
- package/dist-client/server/service/styling/material-tools.d.ts +32 -0
- package/dist-client/server/service/styling/material-tools.js +88 -0
- package/dist-client/server/service/styling/material-tools.js.map +1 -0
- package/dist-client/server/service/styling/read-tools.d.ts +34 -0
- package/dist-client/server/service/styling/read-tools.js +42 -0
- package/dist-client/server/service/styling/read-tools.js.map +1 -0
- package/dist-client/server/service/styling/registry.d.ts +91 -0
- package/dist-client/server/service/styling/registry.js +345 -0
- package/dist-client/server/service/styling/registry.js.map +1 -0
- package/dist-client/server/service/styling/stroke-tools.d.ts +35 -0
- package/dist-client/server/service/styling/stroke-tools.js +94 -0
- package/dist-client/server/service/styling/stroke-tools.js.map +1 -0
- package/dist-client/server/service/styling/text-tools.d.ts +32 -0
- package/dist-client/server/service/styling/text-tools.js +101 -0
- package/dist-client/server/service/styling/text-tools.js.map +1 -0
- package/dist-client/server/service/types.d.ts +265 -0
- package/dist-client/server/service/types.js +2 -0
- package/dist-client/server/service/types.js.map +1 -0
- package/dist-client/server/service/validation/board-model-schema.d.ts +8311 -0
- package/dist-client/server/service/validation/board-model-schema.js +402 -0
- package/dist-client/server/service/validation/board-model-schema.js.map +1 -0
- package/dist-client/server/service/validation/tool-validation.d.ts +31 -0
- package/dist-client/server/service/validation/tool-validation.js +193 -0
- package/dist-client/server/service/validation/tool-validation.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/index.d.ts +23 -0
- package/dist-server/index.js +27 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/service/agentic-loop.d.ts +87 -0
- package/dist-server/service/agentic-loop.js +280 -0
- package/dist-server/service/agentic-loop.js.map +1 -0
- package/dist-server/service/apply-patch.d.ts +47 -0
- package/dist-server/service/apply-patch.js +369 -0
- package/dist-server/service/apply-patch.js.map +1 -0
- package/dist-server/service/assistant.d.ts +84 -0
- package/dist-server/service/assistant.js +2237 -0
- package/dist-server/service/assistant.js.map +1 -0
- package/dist-server/service/board-ai-resolver.d.ts +54 -0
- package/dist-server/service/board-ai-resolver.js +409 -0
- package/dist-server/service/board-ai-resolver.js.map +1 -0
- package/dist-server/service/catalog-resolver.d.ts +18 -0
- package/dist-server/service/catalog-resolver.js +98 -0
- package/dist-server/service/catalog-resolver.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-broadcast.d.ts +13 -0
- package/dist-server/service/chat-message/chat-message-broadcast.js +13 -0
- package/dist-server/service/chat-message/chat-message-broadcast.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-publish.d.ts +6 -0
- package/dist-server/service/chat-message/chat-message-publish.js +27 -0
- package/dist-server/service/chat-message/chat-message-publish.js.map +1 -0
- package/dist-server/service/chat-message/chat-message-subscription.d.ts +8 -0
- package/dist-server/service/chat-message/chat-message-subscription.js +53 -0
- package/dist-server/service/chat-message/chat-message-subscription.js.map +1 -0
- package/dist-server/service/chat-message/chat-message.d.ts +56 -0
- package/dist-server/service/chat-message/chat-message.js +149 -0
- package/dist-server/service/chat-message/chat-message.js.map +1 -0
- package/dist-server/service/chat-message/index.d.ts +5 -0
- package/dist-server/service/chat-message/index.js +12 -0
- package/dist-server/service/chat-message/index.js.map +1 -0
- package/dist-server/service/chat-session/chat-session.d.ts +31 -0
- package/dist-server/service/chat-session/chat-session.js +131 -0
- package/dist-server/service/chat-session/chat-session.js.map +1 -0
- package/dist-server/service/chat-session/index.d.ts +3 -0
- package/dist-server/service/chat-session/index.js +7 -0
- package/dist-server/service/chat-session/index.js.map +1 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.d.ts +30 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.js +112 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.js.map +1 -0
- package/dist-server/service/chat-session-participant/index.d.ts +4 -0
- package/dist-server/service/chat-session-participant/index.js +10 -0
- package/dist-server/service/chat-session-participant/index.js.map +1 -0
- package/dist-server/service/chat-session-participant/invite-notification.d.ts +27 -0
- package/dist-server/service/chat-session-participant/invite-notification.js +30 -0
- package/dist-server/service/chat-session-participant/invite-notification.js.map +1 -0
- package/dist-server/service/chat-session-participant/presence.d.ts +4 -0
- package/dist-server/service/chat-session-participant/presence.js +22 -0
- package/dist-server/service/chat-session-participant/presence.js.map +1 -0
- package/dist-server/service/chat-session-resolver.d.ts +20 -0
- package/dist-server/service/chat-session-resolver.js +356 -0
- package/dist-server/service/chat-session-resolver.js.map +1 -0
- package/dist-server/service/component-tree.d.ts +68 -0
- package/dist-server/service/component-tree.js +73 -0
- package/dist-server/service/component-tree.js.map +1 -0
- package/dist-server/service/index.d.ts +20 -0
- package/dist-server/service/index.js +34 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/mention-marker.d.ts +78 -0
- package/dist-server/service/mention-marker.js +162 -0
- package/dist-server/service/mention-marker.js.map +1 -0
- package/dist-server/service/mention-resolver.d.ts +96 -0
- package/dist-server/service/mention-resolver.js +177 -0
- package/dist-server/service/mention-resolver.js.map +1 -0
- package/dist-server/service/patch-entry/board-patch-broadcast.d.ts +13 -0
- package/dist-server/service/patch-entry/board-patch-broadcast.js +13 -0
- package/dist-server/service/patch-entry/board-patch-broadcast.js.map +1 -0
- package/dist-server/service/patch-entry/board-patch-subscription.d.ts +12 -0
- package/dist-server/service/patch-entry/board-patch-subscription.js +63 -0
- package/dist-server/service/patch-entry/board-patch-subscription.js.map +1 -0
- package/dist-server/service/patch-entry/index.d.ts +4 -0
- package/dist-server/service/patch-entry/index.js +12 -0
- package/dist-server/service/patch-entry/index.js.map +1 -0
- package/dist-server/service/patch-entry/patch-entry.d.ts +16 -0
- package/dist-server/service/patch-entry/patch-entry.js +96 -0
- package/dist-server/service/patch-entry/patch-entry.js.map +1 -0
- package/dist-server/service/prefab-registry.d.ts +73 -0
- package/dist-server/service/prefab-registry.js +258 -0
- package/dist-server/service/prefab-registry.js.map +1 -0
- package/dist-server/service/styling/clear-tools.d.ts +15 -0
- package/dist-server/service/styling/clear-tools.js +53 -0
- package/dist-server/service/styling/clear-tools.js.map +1 -0
- package/dist-server/service/styling/color-utils.d.ts +43 -0
- package/dist-server/service/styling/color-utils.js +210 -0
- package/dist-server/service/styling/color-utils.js.map +1 -0
- package/dist-server/service/styling/copy-tools.d.ts +27 -0
- package/dist-server/service/styling/copy-tools.js +81 -0
- package/dist-server/service/styling/copy-tools.js.map +1 -0
- package/dist-server/service/styling/effect-tools.d.ts +45 -0
- package/dist-server/service/styling/effect-tools.js +90 -0
- package/dist-server/service/styling/effect-tools.js.map +1 -0
- package/dist-server/service/styling/fill-tools.d.ts +60 -0
- package/dist-server/service/styling/fill-tools.js +229 -0
- package/dist-server/service/styling/fill-tools.js.map +1 -0
- package/dist-server/service/styling/material-tools.d.ts +32 -0
- package/dist-server/service/styling/material-tools.js +92 -0
- package/dist-server/service/styling/material-tools.js.map +1 -0
- package/dist-server/service/styling/read-tools.d.ts +34 -0
- package/dist-server/service/styling/read-tools.js +45 -0
- package/dist-server/service/styling/read-tools.js.map +1 -0
- package/dist-server/service/styling/registry.d.ts +91 -0
- package/dist-server/service/styling/registry.js +352 -0
- package/dist-server/service/styling/registry.js.map +1 -0
- package/dist-server/service/styling/stroke-tools.d.ts +35 -0
- package/dist-server/service/styling/stroke-tools.js +97 -0
- package/dist-server/service/styling/stroke-tools.js.map +1 -0
- package/dist-server/service/styling/text-tools.d.ts +32 -0
- package/dist-server/service/styling/text-tools.js +105 -0
- package/dist-server/service/styling/text-tools.js.map +1 -0
- package/dist-server/service/subscribe-auth.d.ts +14 -0
- package/dist-server/service/subscribe-auth.js +33 -0
- package/dist-server/service/subscribe-auth.js.map +1 -0
- package/dist-server/service/types.d.ts +265 -0
- package/dist-server/service/types.js +3 -0
- package/dist-server/service/types.js.map +1 -0
- package/dist-server/service/validation/board-model-schema.d.ts +8311 -0
- package/dist-server/service/validation/board-model-schema.js +409 -0
- package/dist-server/service/validation/board-model-schema.js.map +1 -0
- package/dist-server/service/validation/tool-validation.d.ts +31 -0
- package/dist-server/service/validation/tool-validation.js +196 -0
- package/dist-server/service/validation/tool-validation.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +48 -0
- package/server/index.ts +23 -0
- package/server/service/agentic-loop.test.ts +705 -0
- package/server/service/agentic-loop.ts +431 -0
- package/server/service/apply-patch-drift.test.ts +829 -0
- package/server/service/apply-patch.test.ts +757 -0
- package/server/service/apply-patch.ts +411 -0
- package/server/service/assistant-integration.test.ts +922 -0
- package/server/service/assistant-llm-smoke.test.ts +296 -0
- package/server/service/assistant.test.ts +2034 -0
- package/server/service/assistant.ts +2378 -0
- package/server/service/board-ai-resolver.ts +407 -0
- package/server/service/catalog-resolver.test.ts +137 -0
- package/server/service/catalog-resolver.ts +102 -0
- package/server/service/chat-message/chat-message-broadcast.integration.test.ts +73 -0
- package/server/service/chat-message/chat-message-broadcast.test.ts +40 -0
- package/server/service/chat-message/chat-message-broadcast.ts +27 -0
- package/server/service/chat-message/chat-message-publish.ts +22 -0
- package/server/service/chat-message/chat-message-subscription.ts +41 -0
- package/server/service/chat-message/chat-message.ts +169 -0
- package/server/service/chat-message/index.ts +12 -0
- package/server/service/chat-session/chat-session.ts +130 -0
- package/server/service/chat-session/index.ts +5 -0
- package/server/service/chat-session-participant/chat-session-participant.ts +110 -0
- package/server/service/chat-session-participant/index.ts +6 -0
- package/server/service/chat-session-participant/invite-notification.test.ts +30 -0
- package/server/service/chat-session-participant/invite-notification.ts +48 -0
- package/server/service/chat-session-participant/presence.test.ts +39 -0
- package/server/service/chat-session-participant/presence.ts +21 -0
- package/server/service/chat-session-resolver.ts +312 -0
- package/server/service/component-tree.test.ts +248 -0
- package/server/service/component-tree.ts +135 -0
- package/server/service/index.ts +32 -0
- package/server/service/mention-marker.extract.test.ts +61 -0
- package/server/service/mention-marker.test.ts +228 -0
- package/server/service/mention-marker.ts +184 -0
- package/server/service/mention-resolver.test.ts +273 -0
- package/server/service/mention-resolver.ts +264 -0
- package/server/service/patch-entry/board-patch-broadcast.ts +24 -0
- package/server/service/patch-entry/board-patch-subscription.test.ts +40 -0
- package/server/service/patch-entry/board-patch-subscription.ts +50 -0
- package/server/service/patch-entry/index.ts +12 -0
- package/server/service/patch-entry/patch-entry.ts +89 -0
- package/server/service/prefab-registry.test.ts +172 -0
- package/server/service/prefab-registry.ts +332 -0
- package/server/service/styling/clear-tools.test.ts +164 -0
- package/server/service/styling/clear-tools.ts +69 -0
- package/server/service/styling/color-utils.test.ts +130 -0
- package/server/service/styling/color-utils.ts +226 -0
- package/server/service/styling/copy-tools.test.ts +152 -0
- package/server/service/styling/copy-tools.ts +115 -0
- package/server/service/styling/effect-tools.test.ts +277 -0
- package/server/service/styling/effect-tools.ts +124 -0
- package/server/service/styling/fill-tools.test.ts +331 -0
- package/server/service/styling/fill-tools.ts +293 -0
- package/server/service/styling/material-tools.test.ts +294 -0
- package/server/service/styling/material-tools.ts +114 -0
- package/server/service/styling/read-tools.test.ts +78 -0
- package/server/service/styling/read-tools.ts +67 -0
- package/server/service/styling/registry.test.ts +203 -0
- package/server/service/styling/registry.ts +423 -0
- package/server/service/styling/stroke-tools.test.ts +245 -0
- package/server/service/styling/stroke-tools.ts +145 -0
- package/server/service/styling/text-tools.test.ts +253 -0
- package/server/service/styling/text-tools.ts +131 -0
- package/server/service/styling/tier1-tools.test.ts +300 -0
- package/server/service/subscribe-auth.test.ts +57 -0
- package/server/service/subscribe-auth.ts +34 -0
- package/server/service/types.ts +235 -0
- package/server/service/validation/board-model-schema.test.ts +778 -0
- package/server/service/validation/board-model-schema.ts +446 -0
- package/server/service/validation/tool-validation.ts +228 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +49 -0
- package/translations/ja.json +48 -0
- package/translations/ko.json +49 -0
- package/translations/ms.json +48 -0
- package/translations/zh.json +48 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 실제 LLM 통합 스모크 테스트 (gated).
|
|
3
|
+
*
|
|
4
|
+
* 단위 / 통합 / 호스트 dispatcher 테스트 (3-layer 자동화) 가 mock 으로 잡지 못하는
|
|
5
|
+
* 한 가지: **실제 LLM 이 우리 tool catalog 를 보고 사용자 의도에 맞는 tool 을
|
|
6
|
+
* 선택하는가**. mock 으로는 tool 선택 결정을 시뮬레이션할 수 없다.
|
|
7
|
+
*
|
|
8
|
+
* 정책:
|
|
9
|
+
* - **Default 비활성** — RUN_LLM_SMOKE=1 환경변수 + provider API key 필요.
|
|
10
|
+
* `yarn test` 매 실행마다 돌리면 비용 누적 + 시간 소요 + 외부 의존성.
|
|
11
|
+
* - 릴리즈 게이트 / nightly cron 에서만 실행 권장 (수동: `yarn test:llm-smoke`)
|
|
12
|
+
* - 검증은 **느슨한** 매칭 — LLM 응답은 비결정적이라 tool 이름 집합에 포함되는지만
|
|
13
|
+
* 확인. 정확한 인자값은 검증하지 않는다.
|
|
14
|
+
* - 실패 시 toolUsages 콘솔 출력해서 어떤 tool 을 골랐는지 디버그 가능.
|
|
15
|
+
*
|
|
16
|
+
* Provider 자동 선택 우선순위:
|
|
17
|
+
* 1. LLM_SMOKE_PROVIDER 명시 (anthropic | gemini | openai)
|
|
18
|
+
* 2. 환경 키 보유 순서: ANTHROPIC_API_KEY → GEMINI_API_KEY → OPENAI_API_KEY
|
|
19
|
+
*/
|
|
20
|
+
import {
|
|
21
|
+
createAIClient,
|
|
22
|
+
listRegisteredProviders,
|
|
23
|
+
type AIClient
|
|
24
|
+
} from '@things-factory/ai-client-base'
|
|
25
|
+
import { DefaultBoardAIAssistant } from './assistant'
|
|
26
|
+
import type { ChatOptions } from './types'
|
|
27
|
+
|
|
28
|
+
// providers 자동 등록 — import 만으로 registerAIProvider 발동
|
|
29
|
+
import '@things-factory/ai-client-base'
|
|
30
|
+
|
|
31
|
+
const RUN_FLAG = process.env.RUN_LLM_SMOKE === '1'
|
|
32
|
+
|
|
33
|
+
interface ProviderResolution {
|
|
34
|
+
provider: 'anthropic' | 'gemini' | 'openai'
|
|
35
|
+
apiKey: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resolveProvider(): ProviderResolution | null {
|
|
39
|
+
const explicit = process.env.LLM_SMOKE_PROVIDER as 'anthropic' | 'gemini' | 'openai' | undefined
|
|
40
|
+
const candidates: Array<{ provider: 'anthropic' | 'gemini' | 'openai'; envKey: string }> = [
|
|
41
|
+
{ provider: 'anthropic', envKey: 'ANTHROPIC_API_KEY' },
|
|
42
|
+
{ provider: 'gemini', envKey: 'GEMINI_API_KEY' },
|
|
43
|
+
{ provider: 'openai', envKey: 'OPENAI_API_KEY' }
|
|
44
|
+
]
|
|
45
|
+
if (explicit) {
|
|
46
|
+
const match = candidates.find(c => c.provider === explicit)
|
|
47
|
+
if (match && process.env[match.envKey]) {
|
|
48
|
+
return { provider: match.provider, apiKey: process.env[match.envKey]! }
|
|
49
|
+
}
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
for (const c of candidates) {
|
|
53
|
+
if (process.env[c.envKey]) {
|
|
54
|
+
return { provider: c.provider, apiKey: process.env[c.envKey]! }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const resolved = RUN_FLAG ? resolveProvider() : null
|
|
61
|
+
const ENABLED = !!resolved
|
|
62
|
+
const describeIf = ENABLED ? describe : describe.skip
|
|
63
|
+
|
|
64
|
+
const COMMON_OPTIONS: ChatOptions = {
|
|
65
|
+
knownTypes: ['rect', 'circle', 'text', 'gauge-circle'],
|
|
66
|
+
// 토큰 절약 + 빠른 응답
|
|
67
|
+
maxTokens: 1024,
|
|
68
|
+
temperature: 0.1
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function makeClient(): AIClient {
|
|
72
|
+
// import 만으로는 jest 모듈 캐시 / hoisting 이슈로 registry 가 비어있을 수 있어
|
|
73
|
+
// 호출 시점에 등록 확인.
|
|
74
|
+
if (listRegisteredProviders().length === 0) {
|
|
75
|
+
// 강제 재로딩
|
|
76
|
+
require('@things-factory/ai-client-base')
|
|
77
|
+
}
|
|
78
|
+
return createAIClient({
|
|
79
|
+
provider: resolved!.provider,
|
|
80
|
+
apiKey: resolved!.apiKey
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const TIMEOUT_MS = 90_000 // 다중 turn agentic loop 고려, 90초
|
|
85
|
+
|
|
86
|
+
const dumpUsages = (usages: any) => {
|
|
87
|
+
if (usages) console.log(' toolUsages:', JSON.stringify(usages.map((u: any) => ({ name: u.name, kind: u.kind })), null, 2))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
describeIf('LLM 스모크 — 실제 모델 tool 선택 검증', () => {
|
|
91
|
+
let client: AIClient
|
|
92
|
+
beforeAll(() => {
|
|
93
|
+
client = makeClient()
|
|
94
|
+
// eslint-disable-next-line no-console
|
|
95
|
+
console.log(`[llm-smoke] provider=${resolved!.provider} client.id=${client.id}`)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test(
|
|
99
|
+
'"안녕" → text-only (tool 호출 없음)',
|
|
100
|
+
async () => {
|
|
101
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
102
|
+
const r = await a.chat([{ role: 'user', content: '안녕' }], undefined, COMMON_OPTIONS)
|
|
103
|
+
expect(r.reply).toBeTruthy()
|
|
104
|
+
expect(r.patch).toBeUndefined()
|
|
105
|
+
expect(r.toolUsages ?? []).toHaveLength(0)
|
|
106
|
+
},
|
|
107
|
+
TIMEOUT_MS
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
test(
|
|
111
|
+
'"rect 하나 추가" → addComponent 호출',
|
|
112
|
+
async () => {
|
|
113
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
114
|
+
const r = await a.chat(
|
|
115
|
+
[{ role: 'user', content: 'rect 하나 추가해줘' }],
|
|
116
|
+
{ width: 1000, height: 600, components: [] } as any,
|
|
117
|
+
COMMON_OPTIONS
|
|
118
|
+
)
|
|
119
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
120
|
+
dumpUsages(r.toolUsages)
|
|
121
|
+
expect(names).toContain('addComponent')
|
|
122
|
+
expect(r.patch).toBeDefined()
|
|
123
|
+
expect(r.patch!.ops.some(op => op.op === 'add')).toBe(true)
|
|
124
|
+
},
|
|
125
|
+
TIMEOUT_MS
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
test(
|
|
129
|
+
'"선택한 컴포넌트 빨간색" + selectedRefids → modifyComponentByRefid',
|
|
130
|
+
async () => {
|
|
131
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
132
|
+
const r = await a.chat(
|
|
133
|
+
[{ role: 'user', content: '선택한 컴포넌트를 빨간색으로 바꿔줘' }],
|
|
134
|
+
{
|
|
135
|
+
width: 1000,
|
|
136
|
+
height: 600,
|
|
137
|
+
components: [{ refid: 35, type: 'rect', left: 10, top: 20, fillStyle: '#fff' }]
|
|
138
|
+
} as any,
|
|
139
|
+
{ ...COMMON_OPTIONS, selectedRefids: [35] }
|
|
140
|
+
)
|
|
141
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
142
|
+
dumpUsages(r.toolUsages)
|
|
143
|
+
// 받아들일 수 있는 경로: 직접 modify 또는 먼저 read 후 modify
|
|
144
|
+
expect(names).toContain('modifyComponentByRefid')
|
|
145
|
+
expect(r.patch?.ops.some(op => op.op === 'modify')).toBe(true)
|
|
146
|
+
},
|
|
147
|
+
TIMEOUT_MS
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
test(
|
|
151
|
+
'"왼쪽으로 정렬" + 다중 selection → alignComponents',
|
|
152
|
+
async () => {
|
|
153
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
154
|
+
const r = await a.chat(
|
|
155
|
+
[{ role: 'user', content: '선택한 것들을 왼쪽으로 정렬해줘' }],
|
|
156
|
+
{
|
|
157
|
+
width: 1000,
|
|
158
|
+
height: 600,
|
|
159
|
+
components: [
|
|
160
|
+
{ refid: 1, type: 'rect', left: 10, top: 0, width: 100, height: 50 },
|
|
161
|
+
{ refid: 2, type: 'rect', left: 80, top: 100, width: 100, height: 50 }
|
|
162
|
+
]
|
|
163
|
+
} as any,
|
|
164
|
+
{ ...COMMON_OPTIONS, selectedRefids: [1, 2] }
|
|
165
|
+
)
|
|
166
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
167
|
+
dumpUsages(r.toolUsages)
|
|
168
|
+
expect(names).toContain('alignComponents')
|
|
169
|
+
},
|
|
170
|
+
TIMEOUT_MS
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
test(
|
|
174
|
+
'"보드 배경 어둡게" → modifyBoard',
|
|
175
|
+
async () => {
|
|
176
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
177
|
+
const r = await a.chat(
|
|
178
|
+
[{ role: 'user', content: '보드 배경을 어둡게 해줘' }],
|
|
179
|
+
{ width: 1000, height: 600, fillStyle: '#ffffff', components: [] } as any,
|
|
180
|
+
COMMON_OPTIONS
|
|
181
|
+
)
|
|
182
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
183
|
+
dumpUsages(r.toolUsages)
|
|
184
|
+
// modifyBoard 또는 atmosphere primer + modifyBoard 둘 다 OK
|
|
185
|
+
expect(names).toContain('modifyBoard')
|
|
186
|
+
},
|
|
187
|
+
TIMEOUT_MS
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
test(
|
|
191
|
+
'"심해 분위기로" → getAtmosphereGuide + modifyBoard 패턴',
|
|
192
|
+
async () => {
|
|
193
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
194
|
+
const r = await a.chat(
|
|
195
|
+
[{ role: 'user', content: '이 보드를 심해 분위기로 만들어줘' }],
|
|
196
|
+
{ width: 1000, height: 600, components: [] } as any,
|
|
197
|
+
COMMON_OPTIONS
|
|
198
|
+
)
|
|
199
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
200
|
+
dumpUsages(r.toolUsages)
|
|
201
|
+
// 핵심: AI 가 atmosphere primer 를 활용 (LLM 이 atmosphere 모르더라도 우리
|
|
202
|
+
// primer 가이드를 호출해야 일관된 결과 — 시스템 프롬프트의 의도)
|
|
203
|
+
expect(names).toContain('modifyBoard')
|
|
204
|
+
},
|
|
205
|
+
TIMEOUT_MS
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
test(
|
|
209
|
+
'"view 모드로" → setSceneMode action (ephemeral)',
|
|
210
|
+
async () => {
|
|
211
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
212
|
+
const r = await a.chat(
|
|
213
|
+
[{ role: 'user', content: 'view 모드로 바꿔줘' }],
|
|
214
|
+
{ width: 1000, height: 600, components: [] } as any,
|
|
215
|
+
COMMON_OPTIONS
|
|
216
|
+
)
|
|
217
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
218
|
+
dumpUsages(r.toolUsages)
|
|
219
|
+
expect(names).toContain('setSceneMode')
|
|
220
|
+
// ephemeral — patch 없음, actions 에 들어감
|
|
221
|
+
expect(r.actions?.some(a => a.action === 'setSceneMode')).toBe(true)
|
|
222
|
+
},
|
|
223
|
+
TIMEOUT_MS
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
test(
|
|
227
|
+
'"보드 전체 보이게" → fitToView action',
|
|
228
|
+
async () => {
|
|
229
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
230
|
+
const r = await a.chat(
|
|
231
|
+
[{ role: 'user', content: '보드 전체가 보이게 화면 맞춰줘' }],
|
|
232
|
+
{ width: 2000, height: 1200, components: [{ refid: 1, type: 'rect' }] } as any,
|
|
233
|
+
COMMON_OPTIONS
|
|
234
|
+
)
|
|
235
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
236
|
+
dumpUsages(r.toolUsages)
|
|
237
|
+
expect(names).toContain('fitToView')
|
|
238
|
+
},
|
|
239
|
+
TIMEOUT_MS
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
test(
|
|
243
|
+
'"선택한 거 화면 가운데" + selection → centerToComponent',
|
|
244
|
+
async () => {
|
|
245
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
246
|
+
const r = await a.chat(
|
|
247
|
+
[{ role: 'user', content: '선택한 컴포넌트를 화면 가운데로 보여줘' }],
|
|
248
|
+
{ width: 1000, height: 600, components: [{ refid: 7, type: 'rect' }] } as any,
|
|
249
|
+
{ ...COMMON_OPTIONS, selectedRefids: [7] }
|
|
250
|
+
)
|
|
251
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
252
|
+
dumpUsages(r.toolUsages)
|
|
253
|
+
expect(names).toContain('centerToComponent')
|
|
254
|
+
},
|
|
255
|
+
TIMEOUT_MS
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
test(
|
|
259
|
+
'"refid 1 삭제" → removeComponentByRefid',
|
|
260
|
+
async () => {
|
|
261
|
+
const a = new DefaultBoardAIAssistant(client)
|
|
262
|
+
const r = await a.chat(
|
|
263
|
+
[{ role: 'user', content: 'refid 1번 컴포넌트 삭제해줘' }],
|
|
264
|
+
{
|
|
265
|
+
width: 1000,
|
|
266
|
+
height: 600,
|
|
267
|
+
components: [
|
|
268
|
+
{ refid: 1, type: 'rect' },
|
|
269
|
+
{ refid: 2, type: 'circle' }
|
|
270
|
+
]
|
|
271
|
+
} as any,
|
|
272
|
+
COMMON_OPTIONS
|
|
273
|
+
)
|
|
274
|
+
const names = (r.toolUsages ?? []).map((u: any) => u.name)
|
|
275
|
+
dumpUsages(r.toolUsages)
|
|
276
|
+
expect(names).toContain('removeComponentByRefid')
|
|
277
|
+
expect(r.patch?.ops.some(op => op.op === 'remove')).toBe(true)
|
|
278
|
+
},
|
|
279
|
+
TIMEOUT_MS
|
|
280
|
+
)
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
// ── Skip 안내 — 사용법 노출 ───────────────────────────────────────
|
|
284
|
+
if (!ENABLED) {
|
|
285
|
+
describe('LLM 스모크 — 비활성 안내', () => {
|
|
286
|
+
test('실행 방법', () => {
|
|
287
|
+
// 의도적 no-op — 사용법을 콘솔로만 노출. 비활성 상태에서도 jest 가 1 test 통과로 보고.
|
|
288
|
+
// eslint-disable-next-line no-console
|
|
289
|
+
console.log(
|
|
290
|
+
'[llm-smoke] 비활성. 실행: RUN_LLM_SMOKE=1 ANTHROPIC_API_KEY=sk-... yarn test:llm-smoke ' +
|
|
291
|
+
'(또는 GEMINI_API_KEY / OPENAI_API_KEY 중 하나).'
|
|
292
|
+
)
|
|
293
|
+
expect(true).toBe(true)
|
|
294
|
+
})
|
|
295
|
+
})
|
|
296
|
+
}
|