@things-factory/board-ai 10.0.0-beta.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/client/components/board-ai-chat.test.ts +120 -0
  2. package/client/components/board-ai-chat.ts +1502 -0
  3. package/client/components/chat-input-builder.ts +40 -0
  4. package/client/components/markdown.test.ts +220 -0
  5. package/client/components/markdown.ts +184 -0
  6. package/client/index.ts +11 -0
  7. package/client/tsconfig.json +13 -0
  8. package/client/utils/board-edit-patch.ts +200 -0
  9. package/config/config.development.js +43 -0
  10. package/config/config.production.js +15 -0
  11. package/dist-client/components/board-ai-chat.d.ts +127 -0
  12. package/dist-client/components/board-ai-chat.js +1455 -0
  13. package/dist-client/components/board-ai-chat.js.map +1 -0
  14. package/dist-client/components/board-ai-chat.test.d.ts +1 -0
  15. package/dist-client/components/board-ai-chat.test.js +112 -0
  16. package/dist-client/components/board-ai-chat.test.js.map +1 -0
  17. package/dist-client/components/chat-input-builder.d.ts +30 -0
  18. package/dist-client/components/chat-input-builder.js +25 -0
  19. package/dist-client/components/chat-input-builder.js.map +1 -0
  20. package/dist-client/components/markdown.d.ts +16 -0
  21. package/dist-client/components/markdown.js +167 -0
  22. package/dist-client/components/markdown.js.map +1 -0
  23. package/dist-client/components/markdown.test.d.ts +1 -0
  24. package/dist-client/components/markdown.test.js +187 -0
  25. package/dist-client/components/markdown.test.js.map +1 -0
  26. package/dist-client/index.d.ts +11 -0
  27. package/dist-client/index.js +12 -0
  28. package/dist-client/index.js.map +1 -0
  29. package/dist-client/tsconfig.tsbuildinfo +1 -0
  30. package/dist-client/utils/board-edit-patch.d.ts +73 -0
  31. package/dist-client/utils/board-edit-patch.js +159 -0
  32. package/dist-client/utils/board-edit-patch.js.map +1 -0
  33. package/dist-server/index.d.ts +21 -0
  34. package/dist-server/index.js +25 -0
  35. package/dist-server/index.js.map +1 -0
  36. package/dist-server/service/apply-patch.d.ts +46 -0
  37. package/dist-server/service/apply-patch.js +211 -0
  38. package/dist-server/service/apply-patch.js.map +1 -0
  39. package/dist-server/service/assistant.d.ts +75 -0
  40. package/dist-server/service/assistant.js +1298 -0
  41. package/dist-server/service/assistant.js.map +1 -0
  42. package/dist-server/service/board-ai-resolver.d.ts +40 -0
  43. package/dist-server/service/board-ai-resolver.js +260 -0
  44. package/dist-server/service/board-ai-resolver.js.map +1 -0
  45. package/dist-server/service/chat-message/chat-message.d.ts +24 -0
  46. package/dist-server/service/chat-message/chat-message.js +108 -0
  47. package/dist-server/service/chat-message/chat-message.js.map +1 -0
  48. package/dist-server/service/chat-message/index.d.ts +3 -0
  49. package/dist-server/service/chat-message/index.js +7 -0
  50. package/dist-server/service/chat-message/index.js.map +1 -0
  51. package/dist-server/service/chat-session/chat-session.d.ts +22 -0
  52. package/dist-server/service/chat-session/chat-session.js +109 -0
  53. package/dist-server/service/chat-session/chat-session.js.map +1 -0
  54. package/dist-server/service/chat-session/index.d.ts +3 -0
  55. package/dist-server/service/chat-session/index.js +7 -0
  56. package/dist-server/service/chat-session/index.js.map +1 -0
  57. package/dist-server/service/chat-session-resolver.d.ts +13 -0
  58. package/dist-server/service/chat-session-resolver.js +178 -0
  59. package/dist-server/service/chat-session-resolver.js.map +1 -0
  60. package/dist-server/service/index.d.ts +14 -0
  61. package/dist-server/service/index.js +26 -0
  62. package/dist-server/service/index.js.map +1 -0
  63. package/dist-server/service/patch-entry/index.d.ts +3 -0
  64. package/dist-server/service/patch-entry/index.js +7 -0
  65. package/dist-server/service/patch-entry/index.js.map +1 -0
  66. package/dist-server/service/patch-entry/patch-entry.d.ts +16 -0
  67. package/dist-server/service/patch-entry/patch-entry.js +96 -0
  68. package/dist-server/service/patch-entry/patch-entry.js.map +1 -0
  69. package/dist-server/service/types.d.ts +137 -0
  70. package/dist-server/service/types.js +3 -0
  71. package/dist-server/service/types.js.map +1 -0
  72. package/dist-server/tsconfig.tsbuildinfo +1 -0
  73. package/package.json +47 -0
  74. package/server/index.ts +21 -0
  75. package/server/service/apply-patch.test.ts +640 -0
  76. package/server/service/apply-patch.ts +250 -0
  77. package/server/service/assistant.test.ts +1317 -0
  78. package/server/service/assistant.ts +1431 -0
  79. package/server/service/board-ai-resolver.ts +239 -0
  80. package/server/service/chat-message/chat-message.ts +110 -0
  81. package/server/service/chat-message/index.ts +5 -0
  82. package/server/service/chat-session/chat-session.ts +103 -0
  83. package/server/service/chat-session/index.ts +5 -0
  84. package/server/service/chat-session-resolver.ts +154 -0
  85. package/server/service/index.ts +24 -0
  86. package/server/service/patch-entry/index.ts +5 -0
  87. package/server/service/patch-entry/patch-entry.ts +89 -0
  88. package/server/service/types.ts +138 -0
  89. package/things-factory.config.js +1 -0
  90. package/translations/en.json +39 -0
  91. package/translations/ja.json +39 -0
  92. package/translations/ko.json +40 -0
  93. package/translations/ms.json +39 -0
  94. package/translations/zh.json +39 -0
  95. package/tsconfig.json +9 -0
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PatchEntry = void 0;
4
+ const tslib_1 = require("tslib");
5
+ /**
6
+ * PatchEntry — 보드의 한 변경 단위 (영구 이력).
7
+ *
8
+ * source 별:
9
+ * - 'ai': AI 가 chat 응답에서 생성
10
+ * - 'user-direct': 사용자가 모델러에서 직접 편집 — 변경 이벤트로 자동 기록
11
+ * - 'import': ImportSession 결과 (도면 → 보드)
12
+ *
13
+ * AI 컨텍스트 유지의 핵심: 사용자 직접 편집도 PatchEntry 로 기록되어
14
+ * 다음 chat 호출 시 system 메시지로 자동 합류 → AI 가 모든 변경을 인지.
15
+ */
16
+ const typeorm_1 = require("typeorm");
17
+ const type_graphql_1 = require("type-graphql");
18
+ const graphql_scalars_1 = require("graphql-scalars");
19
+ const env_1 = require("@things-factory/env");
20
+ const chat_session_js_1 = require("../chat-session/chat-session.js");
21
+ const ORMCONFIG = env_1.config.get('ormconfig', {});
22
+ const DATABASE_TYPE = ORMCONFIG.type;
23
+ let PatchEntry = class PatchEntry {
24
+ /** GraphQL 노출용 — JSON 객체로 변환. */
25
+ get opsJson() {
26
+ try {
27
+ return JSON.parse(this.ops || '[]');
28
+ }
29
+ catch {
30
+ return [];
31
+ }
32
+ }
33
+ };
34
+ exports.PatchEntry = PatchEntry;
35
+ tslib_1.__decorate([
36
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
37
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID, { nullable: true }),
38
+ tslib_1.__metadata("design:type", String)
39
+ ], PatchEntry.prototype, "id", void 0);
40
+ tslib_1.__decorate([
41
+ (0, typeorm_1.ManyToOne)(type => chat_session_js_1.ChatSession, session => session.patches, { onDelete: 'CASCADE' }),
42
+ tslib_1.__metadata("design:type", chat_session_js_1.ChatSession)
43
+ ], PatchEntry.prototype, "session", void 0);
44
+ tslib_1.__decorate([
45
+ (0, typeorm_1.RelationId)((patch) => patch.session),
46
+ tslib_1.__metadata("design:type", String)
47
+ ], PatchEntry.prototype, "sessionId", void 0);
48
+ tslib_1.__decorate([
49
+ (0, typeorm_1.Column)({ type: 'varchar', length: 32 }),
50
+ (0, type_graphql_1.Field)({ description: "'ai' | 'user-direct' | 'import'" }),
51
+ tslib_1.__metadata("design:type", String)
52
+ ], PatchEntry.prototype, "source", void 0);
53
+ tslib_1.__decorate([
54
+ (0, typeorm_1.Column)({
55
+ type: DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
56
+ ? 'longtext'
57
+ : DATABASE_TYPE == 'oracle'
58
+ ? 'clob'
59
+ : DATABASE_TYPE == 'mssql'
60
+ ? 'nvarchar'
61
+ : 'text',
62
+ length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined
63
+ }),
64
+ tslib_1.__metadata("design:type", String)
65
+ ], PatchEntry.prototype, "ops", void 0);
66
+ tslib_1.__decorate([
67
+ (0, type_graphql_1.Field)(type => graphql_scalars_1.GraphQLJSON, { description: 'BoardEditOp[] (parsed JSON array).' }),
68
+ tslib_1.__metadata("design:type", Object),
69
+ tslib_1.__metadata("design:paramtypes", [])
70
+ ], PatchEntry.prototype, "opsJson", null);
71
+ tslib_1.__decorate([
72
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
73
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Short human summary of this patch.' }),
74
+ tslib_1.__metadata("design:type", String)
75
+ ], PatchEntry.prototype, "summary", void 0);
76
+ tslib_1.__decorate([
77
+ (0, typeorm_1.Column)({ type: 'float', nullable: true }),
78
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'AI confidence 0..1 (null for user-direct).' }),
79
+ tslib_1.__metadata("design:type", Number)
80
+ ], PatchEntry.prototype, "confidence", void 0);
81
+ tslib_1.__decorate([
82
+ (0, typeorm_1.Column)({ default: false }),
83
+ (0, type_graphql_1.Field)({ description: 'Whether this patch was reverted.' }),
84
+ tslib_1.__metadata("design:type", Boolean)
85
+ ], PatchEntry.prototype, "reverted", void 0);
86
+ tslib_1.__decorate([
87
+ (0, typeorm_1.CreateDateColumn)(),
88
+ (0, type_graphql_1.Field)({ nullable: true }),
89
+ tslib_1.__metadata("design:type", Date)
90
+ ], PatchEntry.prototype, "createdAt", void 0);
91
+ exports.PatchEntry = PatchEntry = tslib_1.__decorate([
92
+ (0, typeorm_1.Entity)(),
93
+ (0, typeorm_1.Index)('ix_patch_entry_1', (patch) => [patch.session, patch.createdAt]),
94
+ (0, type_graphql_1.ObjectType)({ description: 'One board edit operation history (cascade-deleted with ChatSession).' })
95
+ ], PatchEntry);
96
+ //# sourceMappingURL=patch-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-entry.js","sourceRoot":"","sources":["../../../server/service/patch-entry/patch-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PatchEntry — 보드의 한 변경 단위 (영구 이력).\n *\n * source 별:\n * - 'ai': AI 가 chat 응답에서 생성\n * - 'user-direct': 사용자가 모델러에서 직접 편집 — 변경 이벤트로 자동 기록\n * - 'import': ImportSession 결과 (도면 → 보드)\n *\n * AI 컨텍스트 유지의 핵심: 사용자 직접 편집도 PatchEntry 로 기록되어\n * 다음 chat 호출 시 system 메시지로 자동 합류 → AI 가 모든 변경을 인지.\n */\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId\n} from 'typeorm'\nimport { Field, ID, Float, ObjectType } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport { config } from '@things-factory/env'\n\nimport { ChatSession } from '../chat-session/chat-session.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\n@Entity()\n@Index('ix_patch_entry_1', (patch: PatchEntry) => [patch.session, patch.createdAt])\n@ObjectType({ description: 'One board edit operation history (cascade-deleted with ChatSession).' })\nexport class PatchEntry {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true })\n readonly id?: string\n\n @ManyToOne(type => ChatSession, session => session.patches, { onDelete: 'CASCADE' })\n session?: ChatSession\n\n @RelationId((patch: PatchEntry) => patch.session)\n sessionId?: string\n\n /** 'ai' | 'user-direct' | 'import' */\n @Column({ type: 'varchar', length: 32 })\n @Field({ description: \"'ai' | 'user-direct' | 'import'\" })\n source!: string\n\n /** BoardEditOp[] JSON-stringified — column 으로는 long text. */\n @Column({\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined\n })\n ops!: string\n\n /** GraphQL 노출용 — JSON 객체로 변환. */\n @Field(type => GraphQLJSON, { description: 'BoardEditOp[] (parsed JSON array).' })\n get opsJson(): any {\n try {\n return JSON.parse(this.ops || '[]')\n } catch {\n return []\n }\n }\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Short human summary of this patch.' })\n summary?: string\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'AI confidence 0..1 (null for user-direct).' })\n confidence?: number\n\n @Column({ default: false })\n @Field({ description: 'Whether this patch was reverted.' })\n reverted!: boolean\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n}\n"]}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Board AI — 자연어 채팅 인터페이스 타입 정의.
3
+ *
4
+ * 핵심 개념:
5
+ * - 단일 진입점 `chat()`. 의도 분류(생성/편집/스타일/질문)는 AI 의 일.
6
+ * - 출력은 항상 `ChatResponse`. 보드 변경이 있으면 `patch` 동봉.
7
+ * - patch 의 op 는 직교 4 종 (add / remove / modify / replace).
8
+ * style/move 등은 modify.patch 안에 흡수.
9
+ */
10
+ import type { BoardComponent, BoardModel } from '@things-factory/board-import';
11
+ export interface LLMMessage {
12
+ role: 'user' | 'assistant';
13
+ content: string;
14
+ }
15
+ export interface ChatOptions {
16
+ /** board-import 의 registry scope — 등록된 ImportRule 에서 type/category 후보 추출 */
17
+ scopes?: string[];
18
+ /** 사용 가능한 도메인 type (override). 미지정 시 scopes 에서 자동 추출 */
19
+ knownTypes?: string[];
20
+ /** 사용 가능한 카테고리 (override). 미지정 시 scopes 에서 자동 추출 */
21
+ categories?: string[];
22
+ /**
23
+ * 컴포넌트 type 별 유효 속성 스킴.
24
+ * LLM 이 정확한 컴포넌트 생성을 하도록 type 의 description, group, default model 키 전달.
25
+ *
26
+ * 예:
27
+ * [{ type: 'rect', description: 'Rectangle', group: 'shape',
28
+ * properties: { fillStyle: '#fff', strokeStyle: '#000' } }, ...]
29
+ */
30
+ componentSchemas?: ComponentSchema[];
31
+ /**
32
+ * 사용자가 모델러에서 현재 선택한 컴포넌트의 `refid` 목록.
33
+ *
34
+ * refid 는 things-scene 이 모든 컴포넌트에 자동 발급하는 universal numeric handle.
35
+ * id (데이터 바인딩 이름, unique 아님) 와는 다른 개념 — 선택은 항상 refid 로 표현.
36
+ */
37
+ selectedRefids?: number[];
38
+ /** LLM 모델 override */
39
+ model?: string;
40
+ /** LLM 옵션 */
41
+ temperature?: number;
42
+ maxTokens?: number;
43
+ }
44
+ export interface ComponentSchema {
45
+ type: string;
46
+ description?: string;
47
+ group?: string;
48
+ /**
49
+ * 좌표/크기/경로 관련 키들 — type 마다 다름.
50
+ * 예) ['left', 'top', 'width', 'height'] vs ['cx', 'cy', 'radius'] vs ['points']
51
+ * LLM 이 type 별 정확한 좌표 키를 사용하도록 명시.
52
+ */
53
+ geometryKeys?: string[];
54
+ /**
55
+ * 좌표 외 type 특화 속성 (style, value, min/max 등).
56
+ * default 값 또는 keys 만 — LLM 의 token 절감을 위해 호출자가 적절히 압축.
57
+ */
58
+ properties?: Record<string, any>;
59
+ }
60
+ /**
61
+ * AI 가 응답을 만드는 동안 호출한 도구의 시간순 trace.
62
+ *
63
+ * UX 목적 — 사용자가 "왜 이렇게 답했지" 의문 가질 때 fold-able 박스에서 확인.
64
+ * 디버그용 + 신뢰도 향상.
65
+ */
66
+ export interface ToolUsage {
67
+ /** 도구 이름 (예: 'getSelection', 'modifyBoard', 'addComponent') */
68
+ name: string;
69
+ /** 호출 인자 JSON */
70
+ arguments: any;
71
+ /** 도구 결과 — read tool 은 실제 값 (truncated 가능), write tool 은 queued 마커 */
72
+ result: any;
73
+ /** read tool / write tool 분류 */
74
+ kind: 'read' | 'write' | 'unknown';
75
+ }
76
+ export interface ChatResponse {
77
+ /** 사용자에게 보여줄 텍스트 응답 */
78
+ reply: string;
79
+ /** 보드 변경이 있으면 patch */
80
+ patch?: BoardEditPatch;
81
+ /** 모호한 입력 시 명확화 질문 (patch 없음) */
82
+ followUp?: string;
83
+ /** AI 가 응답 만드는 과정에서 호출한 도구들 (시간순). UI fold-able 박스용. */
84
+ toolUsages?: ToolUsage[];
85
+ }
86
+ export interface BoardEditPatch {
87
+ ops: BoardEditOp[];
88
+ /** 사용자 검수용 1-2 문장 요약 */
89
+ summary: string;
90
+ /** 0..1 신뢰도 */
91
+ confidence: number;
92
+ }
93
+ /**
94
+ * 보드 변경 op.
95
+ *
96
+ * 식별자 정책 — 기존 컴포넌트 타깃팅은 `refid` (number) 만 사용.
97
+ * things-scene 의 모든 컴포넌트는 `refid` 를 자동 발급받는다 (universal).
98
+ * `model.id` 는 optional metadata 일 뿐 — 항상 존재하지 않으므로 targeting 에는
99
+ * 부적합. 별개 개념이므로 BoardEditOp / tool 인자에서도 별개 식별자로 분리하지
100
+ * 않고 refid 단일 채널로 일원화.
101
+ *
102
+ * 계층 — 보드는 **최상위 부모** 이고 그 자체로 자기 속성 (fillStyle, width, height,
103
+ * name 등) 을 갖는다. 자식 컴포넌트와 별개. 보드 속성 변경은 `modifyBoard`,
104
+ * 자식 변경은 `modify` (refid 기반).
105
+ *
106
+ * style 변경 / 이동 / 크기 변경 등 자식 컴포넌트의 변경은 모두 `modify.patch` 안에
107
+ * 흡수. 보드 root 속성 변경은 `modifyBoard.patch` 로.
108
+ */
109
+ export type BoardEditOp = {
110
+ op: 'add';
111
+ component: BoardComponent;
112
+ } | {
113
+ op: 'remove';
114
+ refid: number;
115
+ } | {
116
+ op: 'modify';
117
+ refid: number;
118
+ patch: Partial<BoardComponent>;
119
+ } | {
120
+ op: 'modifyBoard';
121
+ patch: Partial<BoardModel>;
122
+ } | {
123
+ op: 'replace';
124
+ board: BoardModel;
125
+ };
126
+ /**
127
+ * BoardAIAssistant — 자연어 채팅으로 보드를 다루는 단일 인터페이스.
128
+ *
129
+ * 사용:
130
+ * const ai = new DefaultBoardAIAssistant(baseClient, { scopes: ['fmsim'] })
131
+ * const r = await ai.chat([{ role: 'user', content: 'AGV 3대 추가' }], currentBoard)
132
+ * if (r.patch) currentBoard = applyBoardEditPatch(currentBoard, r.patch)
133
+ */
134
+ export interface BoardAIAssistant {
135
+ readonly id: string;
136
+ chat(messages: LLMMessage[], currentBoard: BoardModel | undefined, options?: ChatOptions): Promise<ChatResponse>;
137
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../server/service/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Board AI — 자연어 채팅 인터페이스 타입 정의.\n *\n * 핵심 개념:\n * - 단일 진입점 `chat()`. 의도 분류(생성/편집/스타일/질문)는 AI 의 일.\n * - 출력은 항상 `ChatResponse`. 보드 변경이 있으면 `patch` 동봉.\n * - patch 의 op 는 직교 4 종 (add / remove / modify / replace).\n * style/move 등은 modify.patch 안에 흡수.\n */\nimport type { BoardComponent, BoardModel } from '@things-factory/board-import'\n\nexport interface LLMMessage {\n role: 'user' | 'assistant'\n content: string\n}\n\nexport interface ChatOptions {\n /** board-import 의 registry scope — 등록된 ImportRule 에서 type/category 후보 추출 */\n scopes?: string[]\n /** 사용 가능한 도메인 type (override). 미지정 시 scopes 에서 자동 추출 */\n knownTypes?: string[]\n /** 사용 가능한 카테고리 (override). 미지정 시 scopes 에서 자동 추출 */\n categories?: string[]\n /**\n * 컴포넌트 type 별 유효 속성 스킴.\n * LLM 이 정확한 컴포넌트 생성을 하도록 type 의 description, group, default model 키 전달.\n *\n * 예:\n * [{ type: 'rect', description: 'Rectangle', group: 'shape',\n * properties: { fillStyle: '#fff', strokeStyle: '#000' } }, ...]\n */\n componentSchemas?: ComponentSchema[]\n /**\n * 사용자가 모델러에서 현재 선택한 컴포넌트의 `refid` 목록.\n *\n * refid 는 things-scene 이 모든 컴포넌트에 자동 발급하는 universal numeric handle.\n * id (데이터 바인딩 이름, unique 아님) 와는 다른 개념 — 선택은 항상 refid 로 표현.\n */\n selectedRefids?: number[]\n /** LLM 모델 override */\n model?: string\n /** LLM 옵션 */\n temperature?: number\n maxTokens?: number\n}\n\nexport interface ComponentSchema {\n type: string\n description?: string\n group?: string\n /**\n * 좌표/크기/경로 관련 키들 — type 마다 다름.\n * 예) ['left', 'top', 'width', 'height'] vs ['cx', 'cy', 'radius'] vs ['points']\n * LLM 이 type 별 정확한 좌표 키를 사용하도록 명시.\n */\n geometryKeys?: string[]\n /**\n * 좌표 외 type 특화 속성 (style, value, min/max 등).\n * default 값 또는 keys 만 — LLM 의 token 절감을 위해 호출자가 적절히 압축.\n */\n properties?: Record<string, any>\n}\n\n/**\n * AI 가 응답을 만드는 동안 호출한 도구의 시간순 trace.\n *\n * UX 목적 — 사용자가 \"왜 이렇게 답했지\" 의문 가질 때 fold-able 박스에서 확인.\n * 디버그용 + 신뢰도 향상.\n */\nexport interface ToolUsage {\n /** 도구 이름 (예: 'getSelection', 'modifyBoard', 'addComponent') */\n name: string\n /** 호출 인자 JSON */\n arguments: any\n /** 도구 결과 — read tool 은 실제 값 (truncated 가능), write tool 은 queued 마커 */\n result: any\n /** read tool / write tool 분류 */\n kind: 'read' | 'write' | 'unknown'\n}\n\nexport interface ChatResponse {\n /** 사용자에게 보여줄 텍스트 응답 */\n reply: string\n /** 보드 변경이 있으면 patch */\n patch?: BoardEditPatch\n /** 모호한 입력 시 명확화 질문 (patch 없음) */\n followUp?: string\n /** AI 가 응답 만드는 과정에서 호출한 도구들 (시간순). UI fold-able 박스용. */\n toolUsages?: ToolUsage[]\n}\n\nexport interface BoardEditPatch {\n ops: BoardEditOp[]\n /** 사용자 검수용 1-2 문장 요약 */\n summary: string\n /** 0..1 신뢰도 */\n confidence: number\n}\n\n/**\n * 보드 변경 op.\n *\n * 식별자 정책 — 기존 컴포넌트 타깃팅은 `refid` (number) 만 사용.\n * things-scene 의 모든 컴포넌트는 `refid` 를 자동 발급받는다 (universal).\n * `model.id` 는 optional metadata 일 뿐 — 항상 존재하지 않으므로 targeting 에는\n * 부적합. 별개 개념이므로 BoardEditOp / tool 인자에서도 별개 식별자로 분리하지\n * 않고 refid 단일 채널로 일원화.\n *\n * 계층 — 보드는 **최상위 부모** 이고 그 자체로 자기 속성 (fillStyle, width, height,\n * name 등) 을 갖는다. 자식 컴포넌트와 별개. 보드 속성 변경은 `modifyBoard`,\n * 자식 변경은 `modify` (refid 기반).\n *\n * style 변경 / 이동 / 크기 변경 등 자식 컴포넌트의 변경은 모두 `modify.patch` 안에\n * 흡수. 보드 root 속성 변경은 `modifyBoard.patch` 로.\n */\nexport type BoardEditOp =\n | { op: 'add'; component: BoardComponent }\n | { op: 'remove'; refid: number }\n | { op: 'modify'; refid: number; patch: Partial<BoardComponent> }\n | { op: 'modifyBoard'; patch: Partial<BoardModel> }\n | { op: 'replace'; board: BoardModel }\n\n/**\n * BoardAIAssistant — 자연어 채팅으로 보드를 다루는 단일 인터페이스.\n *\n * 사용:\n * const ai = new DefaultBoardAIAssistant(baseClient, { scopes: ['fmsim'] })\n * const r = await ai.chat([{ role: 'user', content: 'AGV 3대 추가' }], currentBoard)\n * if (r.patch) currentBoard = applyBoardEditPatch(currentBoard, r.patch)\n */\nexport interface BoardAIAssistant {\n readonly id: string\n chat(\n messages: LLMMessage[],\n currentBoard: BoardModel | undefined,\n options?: ChatOptions\n ): Promise<ChatResponse>\n}\n"]}