@things-factory/figure-service 10.1.171 → 10.1.176
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-server/service/figure/figure-format.js +13 -13
- package/dist-server/service/figure/figure-format.js.map +1 -1
- package/dist-server/service/figure/figure-tools.js +2 -2
- package/dist-server/service/figure/figure-tools.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/server/service/figure/figure-format.test.ts +13 -5
- package/server/service/figure/figure-format.ts +13 -13
- package/server/service/figure/figure-tools.test.ts +15 -0
- package/server/service/figure/figure-tools.ts +2 -2
- package/translations/en.json +9 -9
- package/translations/ko.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-tools.js","sourceRoot":"","sources":["../../../server/service/figure/figure-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * figure 저작 도구를 어시스턴트 도구 레지스트리에 등록 — **대화면(도크)에서 저작을 돕기 위함.**\n *\n * 왜 필요한가: `proposeFigure` 는 한 번 시키고 한 번 받는다. 그것으로 되는 일이 있지만, 저작은\n * 대개 「이걸 이렇게 고쳐 봐 → 무게가 얼마나 되나 → 발행은 되나」처럼 여러 차례 오간다. 그 대화를\n * 하려면 어시스턴트가 **지금 무엇이 있는지 읽을 수 있어야** 한다. 읽지 못하면 매번 사람이 정본을\n * 붙여 넣어야 하고, 그러면 대화가 아니다.\n *\n * 능력을 복제하지 않는다. figure-service 가 이미 가진 진입점(`inspectSource` · `proposeFigureSteps` ·\n * 조회)을 레지스트리에 투영한다.\n *\n * ── 전부 조회·제안 전용이다 ─────────────────────────────────────────────────\n * 정본을 고치는 도구를 넣지 않는다. 형식의 설계가 그렇게 정해져 있다 — 어시스턴트는 **후보**를\n * 내고, 받을지 버릴지는 저작자가 정한다(`figure-propose-steps.ts`, ADR-0094). 되돌릴 수 없는 조작이 대화면으로\n * 새지 않으므로 전부 `kind: 'read'` 다.\n *\n * 저장은 저작면이 `updateFigure` 로 한다. 그 mutation 은 `figure:mutation` 이 지키고, 대화는\n * `ai-assistant:mutation` 이 지킨다 — 서로 다른 질문이라 서로 다른 권한이 지킨다. figure 가 board\n * 의 권한을 빌리지 않는다.\n *\n * ── No privilege here. The gate reads what the door declares ─────────────────────\n * Until 2026-09-18 each tool carried `privilege: { category: 'figure', ... }`. It matched the door's\n * directive then, and would drift the day the door changed its declaration — and the looser copy wins.\n * Now the gate reads the declaration of each door in `doors` from AUTH's table (ADR-0071 decision 2,\n * addendum). What stays here is **the doors it reaches**.\n *\n * ── 규율을 도구와 함께 보낸다 ───────────────────────────────────────────────\n * 도구 목록만으로는 「언제 반드시 불러야 하는지」를 모른다. twin 이 그 공백에서 사고를 냈다 —\n * 조치 요청에 도구를 부르지 않고 「제안해 두었습니다」라고만 답해, 사용자에게 **없는 버튼을 누르라고\n * 안내했다.** figure 도 똑같은 자리가 있다: 후보 화면(「지금 / 후보」 두 칸)은 **도구 호출 결과에서만**\n * 만들어진다. 문장으로는 아무 일도 일어나지 않는다.\n *\n * ── LLM 이 넘긴 id 를 믿지 않는다 ───────────────────────────────────────────\n * 사람이 목록에서 고르는 길에서는 드러나지 않지만, 모델은 대화 내용에 이끌려 임의의 id 를 넘길 수\n * 있다. 그래서 호출자 도메인 소속을 먼저 확인한다.\n */\nimport { randomUUID } from 'crypto'\nimport { ILike } from 'typeorm'\nimport {\n aiClientFor,\n registerToolCategory,\n type AIImageMediaType,\n type ToolAttachment,\n type ToolCallContext,\n type ToolCategory,\n type ToolImageAttachment,\n type ToolSpec\n} from '@things-factory/ai-client-base'\n\nimport { FIGURE_CONTEXT_BUDGET, figureViewOf, type FigureReadRequest } from './figure-context.js'\n\n/** How many figures a list without search names. */\nconst LIST_LIMIT = 200\n\n/*\n 서버 의존성은 lazy require 다. 등록은 부팅 초반에 평가되고 그때 typeorm DataSource 가 준비되지\n 않았을 수 있다(board-import · twin-ai 와 같은 정책).\n*/\nlet _deps: any | undefined\n\nfunction getDeps(): any {\n if (!_deps) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const shell = require('@things-factory/shell')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const model = require('@hatiolab/figure-model')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const entity = require('./figure.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const format = require('./figure-format.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const proposer = require('./figure-propose-steps.js')\n _deps = {\n getRepository: shell.getRepository,\n Figure: entity.Figure,\n /* The same doors a save and a release go through. The tool reads; it never saves. */\n inspectSource: format.inspectSource,\n parseSource: format.parseSource,\n figureCostOf: model.figureCostOf,\n figureScoreOf: model.figureScoreOf,\n proposeFigureSteps: proposer.proposeFigureSteps,\n isPlaceholderType: model.isPlaceholderType\n }\n }\n return _deps\n}\n\n/** 시험·검증 하네스 전용 주입 시임. 운영 경로에서 호출 금지. */\nexport function __setFigureToolDepsForTest(deps: any): void {\n _deps = deps\n}\n\nfunction requireDomainId(state: any): string {\n const id = state?.domain?.id\n if (!id) {\n // 도메인을 모르면 무엇을 읽어도 남의 것일 수 있다. 조용히 넘기지 않는다.\n throw new Error('domain context is missing — the figure tools cannot resolve tenant scope')\n }\n return id\n}\n\n/**\n * 이 도형이 호출자 도메인 것인가.\n *\n * 모델이 넘긴 id 를 그대로 쓰지 않는다. 없으면 못 찾았다고 말한다 — 「권한이 없다」와 구별해\n * 알려 줄 것이 없다(다른 테넌트에 그 id 가 있다는 사실 자체가 알려 줄 것이 아니다).\n */\nasync function figureInDomain(figureId: string, domainId: string): Promise<any> {\n const { getRepository, Figure } = getDeps()\n const found = await getRepository(Figure).findOne({\n where: { id: figureId, domain: { id: domainId } }\n })\n if (!found) {\n throw new Error(`figure not found in this tenant: ${figureId}`)\n }\n return found\n}\n\n/** The form of a creation id: the row id a new figure's first save inserts it under (`figure-mutation.ts`). */\nconst CREATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\n/**\n * The figure a tool is about: by id, or by its type name, in the caller's domain. None named: none.\n *\n * A figure not saved yet is a subject too (ADR-0061 decision 3): the modeller names it by its creation id, which its first\n * save inserts the row under (ADR-0072 decision 6), so before that save there is no row. It is the figure open on that\n * screen and nothing else: the id the screen has open, with the draft the screen sent. What is read is that draft, put\n * through the save's door like any draft (`sourceForTool`); nothing the server holds is read for it.\n */\nasync function resolveFigureTarget(figureId: string | undefined, domainId: string, host: any): Promise<any> {\n if (!figureId) return undefined\n const { getRepository, Figure } = getDeps()\n const found =\n (await getRepository(Figure).findOne({ where: { id: figureId, domain: { id: domainId } } })) ??\n (await getRepository(Figure).findOne({ where: { type: figureId, domain: { id: domainId } } }))\n if (found) return found\n const draft = host?.draftSource\n if (CREATION_ID.test(figureId) && host?.figureId === figureId && draft && typeof draft === 'object') {\n return { id: figureId, name: typeof draft.name === 'string' ? draft.name : undefined, source: null }\n }\n throw new Error(`figure not found in this tenant: ${figureId}`)\n}\n\n/**\n * The source a tool reads: the draft on screen when the modeller has this figure open, else the stored one.\n *\n * The host context is the browser's, so it is no ground for access: the row is found in the domain first, and the\n * draft is put through the same door a save goes through before anything reads it.\n */\nconst isFigure = (source: any) => source?.version === 'figure-asset-1'\n\n/**\n * A revision is applied by the modeller on the version the model saw (ADR-0094), so only the figure open there can be\n * revised. Said as what is true, with what the assistant can do instead.\n */\nfunction figureNotOpen() {\n return {\n error: 'FIGURE_NOT_OPEN',\n message: 'A revision can be proposed only for the figure open in the modeller.',\n nextStep:\n 'Tell the person to open the figure in the modeller and ask again there. A new figure needs no open one: call proposeFigureCandidate with create: true.'\n }\n}\n\nfunction sourceForTool(row: any, host: any): { source: any; draft: boolean } {\n const draft = host?.figureId === row.id ? host?.draftSource : undefined\n if (!draft) return { source: row.source ? JSON.parse(row.source) : null, draft: false }\n\n if (typeof draft !== 'object' || Array.isArray(draft)) throw new Error('the unsaved draft is not a figure asset')\n const serialized = JSON.stringify(draft)\n /* Validity is the save door's (the kernel's 1 MiB); how much the model is shown is `figure-context`'s. */\n try {\n getDeps().parseSource(serialized)\n } catch (e: any) {\n const findings = Array.isArray(e?.findings) ? e.findings.map((one: any) => one.message).join(' · ') : String(e?.message ?? e)\n throw new Error(`the unsaved draft is invalid: ${findings}`)\n }\n return { source: draft, draft: true }\n}\n\n/** The finite numbers of an untrusted record, by name; none: undefined. */\nfunction numbersOf(record: any): Record<string, number> | undefined {\n if (!record || typeof record !== 'object' || Array.isArray(record)) return undefined\n const kept = Object.entries(record).filter((entry): entry is [string, number] => typeof entry[1] === 'number' && Number.isFinite(entry[1]))\n return kept.length ? Object.fromEntries(kept) : undefined\n}\n\n/**\n * What the person has in view on the open draft: the part selected and what the preview is trying (ADR-0097 §5.6\n * item 5). The model hears it only here, through a read (ADR-0061 decision 3). Told only when it was seen on the version\n * being read -- a selection from another version may name a part that is gone -- and a part only when the draft has it.\n */\nfunction focusOf(host: any, source: any): { selection?: { part: string }; trying?: { clips?: Record<string, number>; controls?: Record<string, number> } } {\n const onThisVersion = (seen: any) => typeof host?.context === 'string' && seen?.context === host.context && seen?.revision === host.revision\n const focus: ReturnType<typeof focusOf> = {}\n\n const part = host?.selection?.part\n const nodes = source?.document?.model?.nodes\n if (typeof part === 'string' && onThisVersion(host.selection) && Array.isArray(nodes) && nodes.some((node: any) => node?.id === part)) {\n focus.selection = { part }\n }\n\n if (onThisVersion(host?.trying)) {\n const clips = numbersOf(host.trying.clips)\n const controls = numbersOf(host.trying.controls)\n if (clips || controls) focus.trying = { ...(clips ? { clips } : {}), ...(controls ? { controls } : {}) }\n }\n return focus\n}\n\n/**\n * 무엇을 고치라는 것인지 대화면 문맥에서 해소한다.\n *\n * 모델이 대상을 안 줬으면 **저작면이 지금 열고 있는 도형**이다. 사용자에게 식별자를 되묻지\n * 않는다 — 화면에 그 도형이 떠 있는데 「어느 도형입니까」를 묻는 것은 문맥을 안 읽은 것이다.\n */\nfunction figureIdFrom(args: any, host: any): string | undefined {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n if (said) return said\n\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (open) return open\n\n return undefined\n}\n\nfunction missingFigureTarget() {\n return {\n error: 'FIGURE_TARGET_REQUIRED',\n message: 'No figure is open on this screen.',\n nextStep: 'For an existing figure, call listFigures and match the user’s requested name or type; ask which figure only if ambiguous. For a new figure, call proposeFigureCandidate with create: true and the user’s prompt. Do not invent an id or repeat this call without a target.'\n }\n}\n\nconst FIGURE_ID_ARG = {\n figureId: {\n type: 'string',\n description: 'The figure to read. Omit to read the one open in the modeller — with its unsaved changes, and also when it is a new figure not saved yet; the server fills it in, and you cannot see which it is. A figure not saved yet is readable only while it is open in the modeller. On the catalog nothing is open, so resolve the figure the person asked for with listFigures first.'\n }\n} as const\n\nconst PARTS_ARG = {\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole (the answer then has `outline` and no `source`): the ids of the parts to read in full, from `outline.parts`. Omit to read the part selected.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of sections to read, such as one named in `outline.omitted` or its `entries` (for example /document/capabilities/bindings/0).'\n }\n} as const\n\n/**\n * A figure too large to show whole, as the model reads it (ADR-0061 2026-10-16 decision 4): its outline and the parts\n * asked for. The full source stays here; what is measured is measured on it.\n */\nfunction partialRead(source: any, request: FigureReadRequest) {\n const view = figureViewOf(source, request)\n if (view.whole) return { source }\n return {\n outline: view.outline,\n partSources: view.parts,\n ...(Object.keys(view.sections ?? {}).length ? { sectionSources: view.sections } : {}),\n ...(view.notRead ? { notRead: view.notRead } : {}),\n note:\n `This figure is too large to read whole (${view.outline!.chars} characters; ${FIGURE_CONTEXT_BUDGET} are read at once), so this is its outline, the parts in partSources and the sections in sectionSources. ` +\n 'Read what a change touches with parts and sections, then pass the same to proposeFigureCandidate: only parts read in full may be changed, and nothing in a section in outline.omitted that was not read.'\n }\n}\n\n/** The parts the model named, as strings; anything else is dropped. */\nconst stringsOf = (list: unknown): string[] =>\n Array.isArray(list) ? list.filter((one: unknown): one is string => typeof one === 'string' && !!one.trim()).map((one: string) => one.trim()) : []\n\n/** An inspection whose findings would crowd the model's context, cut to the budget with how many there were. */\nfunction findingsWithinBudget(inspection: any) {\n const findings = Array.isArray(inspection?.findings) ? inspection.findings : []\n if (JSON.stringify(inspection).length <= FIGURE_CONTEXT_BUDGET) return inspection\n const head = JSON.stringify({ ...inspection, findings: [], truncated: { shown: findings.length, total: findings.length } }).length\n let room = FIGURE_CONTEXT_BUDGET - head\n const shown: any[] = []\n for (const finding of findings) {\n const cost = JSON.stringify(finding).length + 1\n if (cost > room) break\n shown.push(finding)\n room -= cost\n }\n return { ...inspection, findings: shown, truncated: { shown: shown.length, total: findings.length } }\n}\n\n/**\n * 도구 넷.\n *\n * 목록 · 정본 · 발행 판정 · 후보. 저작 대화에서 실제로 묻는 것이 그 넷이다 — 「무엇이 있나」\n * 「지금 어떻게 생겼나」 「발행이 왜 안 되나」 「이렇게 고쳐 봐」.\n */\nfunction figureToolSpecs(): ToolSpec[] {\n return [\n {\n kind: 'read',\n name: 'listFigures',\n /* 이 도메인의 도형 목록 — 저장소를 직접 읽지만 같은 일을 하는 문은 이것이다. */\n doors: ['Query.figures'],\n description:\n 'Lists the figures in this tenant with their type names, states and part counts. ' +\n 'Call it before naming a type — type names are stored identifiers and must not be invented. ' +\n `Without search it lists the ${LIST_LIMIT} most recently changed; when there are more it says truncated, and a figure the person names may be among the rest - list again with search.`,\n schema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Part of a figure name or type name, in any case. Omit to list the most recently changed.'\n }\n }\n },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const { getRepository, Figure } = getDeps()\n const search = typeof args?.search === 'string' ? args.search.trim() : ''\n const domain = { id: domainId }\n /* `_` and `%` in the words are LIKE wildcards: they can only widen what is found, never hide a match. */\n const where = search\n ? [\n { domain, name: ILike(`%${search}%`) },\n { domain, type: ILike(`%${search}%`) }\n ]\n : { domain }\n /* One more than is shown, to know whether there is more without counting the table. */\n const rows = await getRepository(Figure).find({ where, order: { updatedAt: 'DESC' }, take: LIST_LIMIT + 1 })\n const truncated = rows.length > LIST_LIMIT\n return {\n ...(truncated\n ? {\n truncated: true,\n note: `Only the ${LIST_LIMIT} most recently changed are listed. A figure not here may still exist: call listFigures again with search.`\n }\n : {}),\n figures: rows.slice(0, LIST_LIMIT).map((row: any) => ({\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n score: row.score,\n triangles: row.triangles\n }))\n }\n }\n },\n {\n kind: 'read',\n name: 'getFigureSource',\n /* 저장된 도형의 원본. **저장 전 초안**을 물으면 저장소에 갈 것이 없어 화면이 보낸 것을 그대로 돌려준다 —\n * 그 갈래에는 닿는 문이 없지만 `doors: []` 로 적지 않는다. 그러면 저장된 도형을 읽는 권한 검사가 선언에서 사라진다. */\n doors: ['Query.figure'],\n description:\n 'Returns the source (the figure asset) of one figure, with its measured cost ' +\n '(triangles, part groups, and how many of it hold 60fps on one screen). Call it before proposing a revision — ' +\n 'revising without reading it means proposing against a guess. On the figure open in the modeller it also says what ' +\n 'the person has in view: `selection.part` is the part selected - \"this part\" or \"the selected one\" means it - and ' +\n '`trying` the clip and control values the preview is trying, which are not part of the figure. ' +\n 'A figure too large to read whole comes as `outline` (every part by name, shape and what it is fastened to) and ' +\n '`partSources` (the parts read in full) instead of `source`.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG, ...PARTS_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n if (!current.source) {\n // 저장된 정본이 없는 상태가 실제로 있다(새로 만들고 저장 안 한 것). 지어내지 않는다.\n return { id: row.id, type: row.type, name: row.name, source: null, cost: null }\n }\n\n /* Measured as the catalogue measures it: triangles, draw groups, and its grade against one screen. */\n const { figureCostOf, figureScoreOf } = getDeps()\n /* What is in view belongs to the draft on screen; the stored source may be another figure than the one open. */\n const focus = current.draft ? focusOf(ctx?.host, current.source) : {}\n const asked = stringsOf(args?.parts)\n return {\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n ...partialRead(current.source, { parts: asked.length ? asked : focus.selection ? [focus.selection.part] : [], sections: stringsOf(args?.sections) }),\n draft: current.draft,\n cost: figureCostOf(current.source),\n score: figureScoreOf(current.source) ?? null,\n ...focus\n }\n }\n },\n {\n kind: 'read',\n name: 'inspectFigure',\n /* 검사 결과 — 같은 일을 하는 문. */\n doors: ['Query.inspectFigure'],\n description:\n 'Says whether a figure may be released and, when it may not, what is wrong — each finding ' +\n 'carries why it is a problem and what to change. Call it when asked about releasing, or ' +\n 'when asked to fix a figure that will not release.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n const { inspectSource } = getDeps()\n /* Inspected whole, here; only what the model is told is held to its budget. */\n return { ...findingsWithinBudget(inspectSource(current.source ? JSON.stringify(current.source) : null, null, undefined, row.type)), draft: current.draft }\n }\n },\n {\n kind: 'read',\n name: 'proposeFigureCandidate',\n /* 후보 생성 — 저장은 하지 않지만 같은 문의 권한을 쓴다. */\n doors: ['Mutation.proposeFigure'],\n description:\n 'Asks for a proposal: the modeller commands that make a new figure or revise the one open in the modeller. ' +\n 'Returns the commands with the score and cost of the figure they make. NOTHING IS SAVED — the author applies ' +\n 'the proposal in the modeller as one step, or leaves it. This is the only way a proposal reaches the screen.',\n schema: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description: 'What to make or change, in the words the author used.'\n },\n figureId: {\n type: 'string',\n description: 'Revise this figure; it must be the one open in the modeller. Omit to revise the open one; pass null to create anew.'\n },\n name: {\n type: 'string',\n description: 'The name a person reads for a new figure.'\n },\n create: {\n type: 'boolean',\n description: 'True to create rather than revise, even with a figure open.'\n },\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: the parts this change touches, read first with getFigureSource parts. Only these and the part selected may be changed; new parts may be added and fastened to any part.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of the sections in outline.omitted this change touches, read first with getFigureSource sections. Nothing else in those sections may be changed.'\n }\n },\n required: ['prompt']\n },\n builder: async (args: any, ctx: ToolCallContext) => {\n const domainId = requireDomainId(ctx?.state)\n const prompt = typeof args?.prompt === 'string' ? args.prompt.trim() : ''\n if (!prompt) throw new Error('prompt is required: there is nothing to ask for')\n\n /*\n 고치는 것인지 만드는 것인지를 **문맥에서 정한다.** 열린 도형이 있으면 고치는 것이 기본이고,\n 모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는 도형을 덮어쓰는\n 후보가 온다.\n\n 고치는 제안은 모델러가 **요청 당시의 판(context · revision)** 위에 한 단계로 적용한다(ADR-0094).\n 그래서 고칠 수 있는 것은 모델러에 열린 도형뿐이고, 그 판을 문맥이 함께 실어 와야 한다.\n */\n const host = ctx?.host\n const create = args?.create === true || args?.figureId === null\n let base: unknown\n let figureId: string | undefined\n let focus: ReturnType<typeof focusOf> | undefined\n if (!create) {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (said && said !== open) {\n await figureInDomain(said, domainId)\n return figureNotOpen()\n }\n if (!open) return missingFigureTarget()\n const row = await resolveFigureTarget(open, domainId, host)\n if (!row) return missingFigureTarget()\n const current = sourceForTool(row, host)\n base = current.source ?? undefined\n if (!isFigure(base)) return figureNotOpen()\n if (typeof host?.context !== 'string' || !Number.isInteger(host?.revision)) return figureNotOpen()\n figureId = open\n /* \"Make this one bigger\": the part selected is what the request points at. */\n if (current.draft) focus = focusOf(host, base)\n }\n\n /*\n The pictures the person sent with this turn, as the server checked them (ADR-0061, 2026-10-16 decision 2) --\n every one, in the order attached. Never from the host context: the client fills it.\n */\n const images = (ctx?.attachments ?? [])\n .filter((file: ToolAttachment): file is ToolImageAttachment => file.kind === 'image')\n .map(file => ({ data: file.data, mediaType: file.mediaType as AIImageMediaType }))\n\n const { proposeFigureSteps } = getDeps()\n let result: any\n try {\n result = await proposeFigureSteps({\n /* The agent of this conversation's turn - the one the person picked, or the domain default. */\n client: await aiClientFor({\n domain: ctx?.state?.domain,\n user: ctx?.state?.user,\n agentId: ctx?.state?.aiAgentId,\n modeKind: ctx?.mode?.kind\n }),\n prompt,\n base,\n name: typeof args?.name === 'string' && args.name.trim() ? args.name.trim() : undefined,\n ...(images.length ? { images } : {}),\n ...(focus && Object.keys(focus).length ? { focus } : {}),\n ...(!create && (stringsOf(args?.parts).length || stringsOf(args?.sections).length)\n ? { read: { parts: stringsOf(args?.parts), sections: stringsOf(args?.sections) } }\n : {})\n })\n } catch (error) {\n /*\n * 세 번 거절된 끝의 사유를 ProposeFigureFailure.reasons 에만 두면 agentic-loop 은 「만들지 못했습니다」만\n * 받아 화면에는 「응답이 비어있습니다」가 된다. 다시 시도할 수 있는 말로 경계를 넘긴다.\n * 다른 예외(권한·통신)는 원문을 보존한다.\n */\n const reasons = Array.isArray((error as any)?.reasons) ? (error as any).reasons : []\n if (reasons.length > 0) throw new Error([(error as Error).message, ...reasons].join('\\n'))\n throw error\n }\n\n /*\n **`proposed: true` 가 카드를 만든다.** 이 표시가 없으면 제안은 도구 추적 안에 묻히고 화면에는\n 아무것도 생기지 않는다. 카드의 실행 단추가 figure-ui 의 처리기에 넘기고, 처리기가 모델러에 명령\n 목록을 한 단계로 적용한다. `args` 는 같은 제안을 두 번 세지 않기 위한 열쇠의 일부다.\n */\n const name = result.source.name || 'Figure'\n /* The card is read by a person, so the server writes it in the request's language (ADR-0061, 2026-10-16 decision 1). */\n const t = ctx.t\n return {\n proposed: true,\n /*\n The proposal's own name, given once here (ADR-0097 §5.6 item 5; AI lane, 09-27): the dock keys its card by\n it, a new figure made from it is created under it (the row id), and a save records it -- so what became of\n it can be asked after a reload, and the same proposal never makes two figures.\n */\n key: randomUUID(),\n icon: 'view_in_ar',\n label: create\n ? t('figure.proposal.label-create', { name, defaultValue: 'Make {name}' })\n : t('figure.proposal.label-revise', { name, defaultValue: 'Revise {name}' }),\n reason: t('figure.proposal.reason', {\n steps: result.steps.length,\n grade: result.score?.grade ?? '-',\n triangles: result.cost.triangles,\n attempts: result.attempts,\n defaultValue: '{steps} commands · grade {grade} · {triangles} triangles · made in {attempts} tries'\n }),\n args: { prompt, figureId, create },\n create,\n figureId,\n context: create ? undefined : host.context,\n revision: create ? undefined : host.revision,\n steps: result.steps,\n score: result.score,\n cost: result.cost,\n attempts: result.attempts\n }\n }\n }\n ] as ToolSpec[]\n}\n\n/**\n * 등록 — 부팅 시 1회.\n *\n * 범주가 하나다. twin 은 관찰과 생성을 둘로 갈랐는데(운영 협의에 생성 도구가 들려 있으면 대화의\n * 성격이 흐려진다), figure 의 대화면은 저작면 하나뿐이고 그 자리에서 읽기와 후보 요청이 함께 필요하다.\n * 대화면이 늘면 그때 가른다.\n */\nexport function registerFigureToolCategories(): void {\n const authoring: ToolCategory = {\n name: 'figure-authoring',\n description: 'Reads the source, cost and release verdict of the figure being authored, and proposes changes (nothing is saved).',\n guidance: [\n '- **For a request to make or change a figure, always call `proposeFigureCandidate`.** A proposal exists only as the result of that call.',\n ' Writing \"I made a proposal\" or \"press apply\" without the call is **false**: no card appears, and the person looks for a button that does not exist.',\n ' A proposal is a list of modeller commands. The modeller applies it as one step only when the person runs it from the dock card, and one undo takes it all back. Do not say the figure has changed before that.',\n ' A revision can be proposed only for the figure open in the modeller. Say what the result\\'s `steps` do as they are; do not invent changes the commands do not make.',\n '- Never save the source yourself. Propose; the author decides on the screen whether to take it.',\n '- Name coordinates and sizes by their X/Y/Z axes. Do not attach width, depth or height meanings that have not been confirmed.',\n '- **For a request to change a figure, call `getFigureSource` first.** Revising without reading proposes against a guess, and a renamed part breaks the bindings of the boards it is already placed on.',\n '- On the catalog nothing is open. To read an existing figure, find the id of the name or type the person said with `listFigures`; ask which figure only when it is ambiguous. To revise an existing figure, tell the person to open it in the modeller and ask there. For a new figure, do not read existing sources: call `proposeFigureCandidate` with create: true.',\n '- Do not invent type names; check them with `listFigures`. **A type name is a stored identifier**, and boards find the figure by it. A new figure\\'s type is set by a person at its first save.',\n '- When asked why a figure will not release, call `inspectFigure`. Do not say it can be released without its verdict.',\n ' Each finding carries **why it is a problem and what to change**. Pass it on as it is; a summary makes the author look again for which axis of which part to fix.',\n '- For weight or triangle counts, use `cost` from `getFigureSource`. Do not estimate.'\n ].join('\\n'),\n specs: figureToolSpecs()\n }\n\n registerToolCategory(authoring)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-tools.js","sourceRoot":"","sources":["../../../server/service/figure/figure-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * figure 저작 도구를 어시스턴트 도구 레지스트리에 등록 — **대화면(도크)에서 저작을 돕기 위함.**\n *\n * 왜 필요한가: `proposeFigure` 는 한 번 시키고 한 번 받는다. 그것으로 되는 일이 있지만, 저작은\n * 대개 「이걸 이렇게 고쳐 봐 → 무게가 얼마나 되나 → 발행은 되나」처럼 여러 차례 오간다. 그 대화를\n * 하려면 어시스턴트가 **지금 무엇이 있는지 읽을 수 있어야** 한다. 읽지 못하면 매번 사람이 정본을\n * 붙여 넣어야 하고, 그러면 대화가 아니다.\n *\n * 능력을 복제하지 않는다. figure-service 가 이미 가진 진입점(`inspectSource` · `proposeFigureSteps` ·\n * 조회)을 레지스트리에 투영한다.\n *\n * ── 전부 조회·제안 전용이다 ─────────────────────────────────────────────────\n * 정본을 고치는 도구를 넣지 않는다. 형식의 설계가 그렇게 정해져 있다 — 어시스턴트는 **후보**를\n * 내고, 받을지 버릴지는 저작자가 정한다(`figure-propose-steps.ts`, ADR-0094). 되돌릴 수 없는 조작이 대화면으로\n * 새지 않으므로 전부 `kind: 'read'` 다.\n *\n * 저장은 저작면이 `updateFigure` 로 한다. 그 mutation 은 `figure:mutation` 이 지키고, 대화는\n * `ai-assistant:mutation` 이 지킨다 — 서로 다른 질문이라 서로 다른 권한이 지킨다. figure 가 board\n * 의 권한을 빌리지 않는다.\n *\n * ── No privilege here. The gate reads what the door declares ─────────────────────\n * Until 2026-09-18 each tool carried `privilege: { category: 'figure', ... }`. It matched the door's\n * directive then, and would drift the day the door changed its declaration — and the looser copy wins.\n * Now the gate reads the declaration of each door in `doors` from AUTH's table (ADR-0071 decision 2,\n * addendum). What stays here is **the doors it reaches**.\n *\n * ── 규율을 도구와 함께 보낸다 ───────────────────────────────────────────────\n * 도구 목록만으로는 「언제 반드시 불러야 하는지」를 모른다. twin 이 그 공백에서 사고를 냈다 —\n * 조치 요청에 도구를 부르지 않고 「제안해 두었습니다」라고만 답해, 사용자에게 **없는 버튼을 누르라고\n * 안내했다.** figure 도 똑같은 자리가 있다: 후보 화면(「지금 / 후보」 두 칸)은 **도구 호출 결과에서만**\n * 만들어진다. 문장으로는 아무 일도 일어나지 않는다.\n *\n * ── LLM 이 넘긴 id 를 믿지 않는다 ───────────────────────────────────────────\n * 사람이 목록에서 고르는 길에서는 드러나지 않지만, 모델은 대화 내용에 이끌려 임의의 id 를 넘길 수\n * 있다. 그래서 호출자 도메인 소속을 먼저 확인한다.\n */\nimport { randomUUID } from 'crypto'\nimport { ILike } from 'typeorm'\nimport {\n aiClientFor,\n registerToolCategory,\n type AIImageMediaType,\n type ToolAttachment,\n type ToolCallContext,\n type ToolCategory,\n type ToolImageAttachment,\n type ToolSpec\n} from '@things-factory/ai-client-base'\n\nimport { FIGURE_CONTEXT_BUDGET, figureViewOf, type FigureReadRequest } from './figure-context.js'\n\n/** How many figures a list without search names. */\nconst LIST_LIMIT = 200\n\n/*\n 서버 의존성은 lazy require 다. 등록은 부팅 초반에 평가되고 그때 typeorm DataSource 가 준비되지\n 않았을 수 있다(board-import · twin-ai 와 같은 정책).\n*/\nlet _deps: any | undefined\n\nfunction getDeps(): any {\n if (!_deps) {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const shell = require('@things-factory/shell')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const model = require('@hatiolab/figure-model')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const entity = require('./figure.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const format = require('./figure-format.js')\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const proposer = require('./figure-propose-steps.js')\n _deps = {\n getRepository: shell.getRepository,\n Figure: entity.Figure,\n /* The same doors a save and a release go through. The tool reads; it never saves. */\n inspectSource: format.inspectSource,\n parseSource: format.parseSource,\n figureCostOf: model.figureCostOf,\n figureScoreOf: model.figureScoreOf,\n proposeFigureSteps: proposer.proposeFigureSteps,\n isPlaceholderType: model.isPlaceholderType\n }\n }\n return _deps\n}\n\n/** 시험·검증 하네스 전용 주입 시임. 운영 경로에서 호출 금지. */\nexport function __setFigureToolDepsForTest(deps: any): void {\n _deps = deps\n}\n\nfunction requireDomainId(state: any): string {\n const id = state?.domain?.id\n if (!id) {\n // 도메인을 모르면 무엇을 읽어도 남의 것일 수 있다. 조용히 넘기지 않는다.\n throw new Error('domain context is missing — the figure tools cannot resolve tenant scope')\n }\n return id\n}\n\n/**\n * 이 도형이 호출자 도메인 것인가.\n *\n * 모델이 넘긴 id 를 그대로 쓰지 않는다. 없으면 못 찾았다고 말한다 — 「권한이 없다」와 구별해\n * 알려 줄 것이 없다(다른 테넌트에 그 id 가 있다는 사실 자체가 알려 줄 것이 아니다).\n */\nasync function figureInDomain(figureId: string, domainId: string): Promise<any> {\n const { getRepository, Figure } = getDeps()\n const found = await getRepository(Figure).findOne({\n where: { id: figureId, domain: { id: domainId } }\n })\n if (!found) {\n throw new Error(`figure not found in this tenant: ${figureId}`)\n }\n return found\n}\n\n/** The form of a creation id: the row id a new figure's first save inserts it under (`figure-mutation.ts`). */\nconst CREATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\n/**\n * The figure a tool is about: by id, or by its type name, in the caller's domain. None named: none.\n *\n * A figure not saved yet is a subject too (ADR-0061 decision 3): the modeller names it by its creation id, which its first\n * save inserts the row under (ADR-0072 decision 6), so before that save there is no row. It is the figure open on that\n * screen and nothing else: the id the screen has open, with the draft the screen sent. What is read is that draft, put\n * through the save's door like any draft (`sourceForTool`); nothing the server holds is read for it.\n */\nasync function resolveFigureTarget(figureId: string | undefined, domainId: string, host: any): Promise<any> {\n if (!figureId) return undefined\n const { getRepository, Figure } = getDeps()\n const found =\n (await getRepository(Figure).findOne({ where: { id: figureId, domain: { id: domainId } } })) ??\n (await getRepository(Figure).findOne({ where: { type: figureId, domain: { id: domainId } } }))\n if (found) return found\n const draft = host?.draftSource\n if (CREATION_ID.test(figureId) && host?.figureId === figureId && draft && typeof draft === 'object') {\n return { id: figureId, name: typeof draft.name === 'string' ? draft.name : undefined, source: null }\n }\n throw new Error(`figure not found in this tenant: ${figureId}`)\n}\n\n/**\n * The source a tool reads: the draft on screen when the modeller has this figure open, else the stored one.\n *\n * The host context is the browser's, so it is no ground for access: the row is found in the domain first, and the\n * draft is put through the same door a save goes through before anything reads it.\n */\nconst isFigure = (source: any) => source?.version === 'figure-asset-1'\n\n/**\n * A revision is applied by the modeller on the version the model saw (ADR-0094), so only the figure open there can be\n * revised. Said as what is true, with what the assistant can do instead.\n */\nfunction figureNotOpen() {\n return {\n error: 'FIGURE_NOT_OPEN',\n message: 'A revision can be proposed only for the figure open in the modeller.',\n nextStep:\n 'Tell the person to open the figure in the modeller and ask again there. A new figure needs no open one: call proposeFigureCandidate with create: true.'\n }\n}\n\nfunction sourceForTool(row: any, host: any): { source: any; draft: boolean } {\n const draft = host?.figureId === row.id ? host?.draftSource : undefined\n if (!draft) return { source: row.source ? JSON.parse(row.source) : null, draft: false }\n\n if (typeof draft !== 'object' || Array.isArray(draft)) throw new Error('the unsaved draft is not a figure asset')\n const serialized = JSON.stringify(draft)\n /* Validity is the save door's (the kernel's 1 MiB); how much the model is shown is `figure-context`'s. */\n try {\n getDeps().parseSource(serialized)\n } catch (e: any) {\n const findings = Array.isArray(e?.findings) ? e.findings.map((one: any) => one.message).join(' · ') : String(e?.message ?? e)\n throw new Error(`the unsaved draft is invalid: ${findings}`)\n }\n return { source: draft, draft: true }\n}\n\n/** The finite numbers of an untrusted record, by name; none: undefined. */\nfunction numbersOf(record: any): Record<string, number> | undefined {\n if (!record || typeof record !== 'object' || Array.isArray(record)) return undefined\n const kept = Object.entries(record).filter((entry): entry is [string, number] => typeof entry[1] === 'number' && Number.isFinite(entry[1]))\n return kept.length ? Object.fromEntries(kept) : undefined\n}\n\n/**\n * What the person has in view on the open draft: the part selected and what the preview is trying (ADR-0097 §5.6\n * item 5). The model hears it only here, through a read (ADR-0061 decision 3). Told only when it was seen on the version\n * being read -- a selection from another version may name a part that is gone -- and a part only when the draft has it.\n */\nfunction focusOf(host: any, source: any): { selection?: { part: string }; trying?: { clips?: Record<string, number>; controls?: Record<string, number> } } {\n const onThisVersion = (seen: any) => typeof host?.context === 'string' && seen?.context === host.context && seen?.revision === host.revision\n const focus: ReturnType<typeof focusOf> = {}\n\n const part = host?.selection?.part\n const nodes = source?.document?.model?.nodes\n if (typeof part === 'string' && onThisVersion(host.selection) && Array.isArray(nodes) && nodes.some((node: any) => node?.id === part)) {\n focus.selection = { part }\n }\n\n if (onThisVersion(host?.trying)) {\n const clips = numbersOf(host.trying.clips)\n const controls = numbersOf(host.trying.controls)\n if (clips || controls) focus.trying = { ...(clips ? { clips } : {}), ...(controls ? { controls } : {}) }\n }\n return focus\n}\n\n/**\n * 무엇을 고치라는 것인지 대화면 문맥에서 해소한다.\n *\n * 모델이 대상을 안 줬으면 **저작면이 지금 열고 있는 도형**이다. 사용자에게 식별자를 되묻지\n * 않는다 — 화면에 그 도형이 떠 있는데 「어느 도형입니까」를 묻는 것은 문맥을 안 읽은 것이다.\n */\nfunction figureIdFrom(args: any, host: any): string | undefined {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n if (said) return said\n\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (open) return open\n\n return undefined\n}\n\nfunction missingFigureTarget() {\n return {\n error: 'FIGURE_TARGET_REQUIRED',\n message: 'No figure is open on this screen.',\n nextStep: 'For an existing figure, call listFigures and match the user’s requested name or type; ask which figure only if ambiguous. For a new figure, call proposeFigureCandidate with create: true and the user’s prompt. Do not invent an id or repeat this call without a target.'\n }\n}\n\nconst FIGURE_ID_ARG = {\n figureId: {\n type: 'string',\n description: 'The figure to read. Omit to read the one open in the modeller — with its unsaved changes, and also when it is a new figure not saved yet; the server fills it in, and you cannot see which it is. A figure not saved yet is readable only while it is open in the modeller. On the catalog nothing is open, so resolve the figure the person asked for with listFigures first.'\n }\n} as const\n\nconst PARTS_ARG = {\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole (the answer then has `outline` and no `source`): the ids of the parts to read in full, from `outline.parts`. Omit to read the part selected.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of sections to read, such as one named in `outline.omitted` or its `entries` (for example /document/capabilities/bindings/0).'\n }\n} as const\n\n/**\n * A figure too large to show whole, as the model reads it (ADR-0061 2026-10-16 decision 4): its outline and the parts\n * asked for. The full source stays here; what is measured is measured on it.\n */\nfunction partialRead(source: any, request: FigureReadRequest) {\n const view = figureViewOf(source, request)\n if (view.whole) return { source }\n return {\n outline: view.outline,\n partSources: view.parts,\n ...(Object.keys(view.sections ?? {}).length ? { sectionSources: view.sections } : {}),\n ...(view.notRead ? { notRead: view.notRead } : {}),\n note:\n `This figure is too large to read whole (${view.outline!.chars} characters; ${FIGURE_CONTEXT_BUDGET} are read at once), so this is its outline, the parts in partSources and the sections in sectionSources. ` +\n 'Read what a change touches with parts and sections, then pass the same to proposeFigureCandidate: only parts read in full may be changed, and nothing in a section in outline.omitted that was not read.'\n }\n}\n\n/** The parts the model named, as strings; anything else is dropped. */\nconst stringsOf = (list: unknown): string[] =>\n Array.isArray(list) ? list.filter((one: unknown): one is string => typeof one === 'string' && !!one.trim()).map((one: string) => one.trim()) : []\n\n/** An inspection whose findings would crowd the model's context, cut to the budget with how many there were. */\nfunction findingsWithinBudget(inspection: any) {\n const findings = Array.isArray(inspection?.findings) ? inspection.findings : []\n if (JSON.stringify(inspection).length <= FIGURE_CONTEXT_BUDGET) return inspection\n const head = JSON.stringify({ ...inspection, findings: [], truncated: { shown: findings.length, total: findings.length } }).length\n let room = FIGURE_CONTEXT_BUDGET - head\n const shown: any[] = []\n for (const finding of findings) {\n const cost = JSON.stringify(finding).length + 1\n if (cost > room) break\n shown.push(finding)\n room -= cost\n }\n return { ...inspection, findings: shown, truncated: { shown: shown.length, total: findings.length } }\n}\n\n/**\n * 도구 넷.\n *\n * 목록 · 정본 · 발행 판정 · 후보. 저작 대화에서 실제로 묻는 것이 그 넷이다 — 「무엇이 있나」\n * 「지금 어떻게 생겼나」 「발행이 왜 안 되나」 「이렇게 고쳐 봐」.\n */\nfunction figureToolSpecs(): ToolSpec[] {\n return [\n {\n kind: 'read',\n name: 'listFigures',\n /* 이 도메인의 도형 목록 — 저장소를 직접 읽지만 같은 일을 하는 문은 이것이다. */\n doors: ['Query.figures'],\n description:\n 'Lists the figures in this tenant with their type names, states and part counts. ' +\n 'Call it before naming a type — type names are stored identifiers and must not be invented. ' +\n `Without search it lists the ${LIST_LIMIT} most recently changed; when there are more it says truncated, and a figure the person names may be among the rest - list again with search.`,\n schema: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description: 'Part of a figure name or type name, in any case. Omit to list the most recently changed.'\n }\n }\n },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const { getRepository, Figure } = getDeps()\n const search = typeof args?.search === 'string' ? args.search.trim() : ''\n const domain = { id: domainId }\n /* `_` and `%` in the words are LIKE wildcards: they can only widen what is found, never hide a match. */\n const where = search\n ? [\n { domain, name: ILike(`%${search}%`) },\n { domain, type: ILike(`%${search}%`) }\n ]\n : { domain }\n /* One more than is shown, to know whether there is more without counting the table. */\n const rows = await getRepository(Figure).find({ where, order: { updatedAt: 'DESC' }, take: LIST_LIMIT + 1 })\n const truncated = rows.length > LIST_LIMIT\n return {\n ...(truncated\n ? {\n truncated: true,\n note: `Only the ${LIST_LIMIT} most recently changed are listed. A figure not here may still exist: call listFigures again with search.`\n }\n : {}),\n figures: rows.slice(0, LIST_LIMIT).map((row: any) => ({\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n score: row.score,\n triangles: row.triangles\n }))\n }\n }\n },\n {\n kind: 'read',\n name: 'getFigureSource',\n /* 저장된 도형의 원본. **저장 전 초안**을 물으면 저장소에 갈 것이 없어 화면이 보낸 것을 그대로 돌려준다 —\n * 그 갈래에는 닿는 문이 없지만 `doors: []` 로 적지 않는다. 그러면 저장된 도형을 읽는 권한 검사가 선언에서 사라진다. */\n doors: ['Query.figure'],\n description:\n 'Returns the source (the figure asset) of one figure, with its measured cost ' +\n '(triangles, part groups, and how many of it hold 60fps on one screen). Call it before proposing a revision — ' +\n 'revising without reading it means proposing against a guess. On the figure open in the modeller it also says what ' +\n 'the person has in view: `selection.part` is the part selected - \"this part\" or \"the selected one\" means it - and ' +\n '`trying` the clip and control values the preview is trying, which are not part of the figure. ' +\n 'A figure too large to read whole comes as `outline` (every part by name, shape and what it is fastened to) and ' +\n '`partSources` (the parts read in full) instead of `source`.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG, ...PARTS_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n if (!current.source) {\n // 저장된 정본이 없는 상태가 실제로 있다(새로 만들고 저장 안 한 것). 지어내지 않는다.\n return { id: row.id, type: row.type, name: row.name, source: null, cost: null }\n }\n\n /* Measured as the catalogue measures it: triangles, draw groups, and its grade against one screen. */\n const { figureCostOf, figureScoreOf } = getDeps()\n /* What is in view belongs to the draft on screen; the stored source may be another figure than the one open. */\n const focus = current.draft ? focusOf(ctx?.host, current.source) : {}\n const asked = stringsOf(args?.parts)\n return {\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n ...partialRead(current.source, { parts: asked.length ? asked : focus.selection ? [focus.selection.part] : [], sections: stringsOf(args?.sections) }),\n draft: current.draft,\n cost: figureCostOf(current.source),\n score: figureScoreOf(current.source) ?? null,\n ...focus\n }\n }\n },\n {\n kind: 'read',\n name: 'inspectFigure',\n /* 검사 결과 — 같은 일을 하는 문. */\n doors: ['Query.inspectFigure'],\n description:\n 'Says whether a figure may be released and, when it may not, what is wrong — each finding ' +\n 'carries why it is a problem and what to change. Call it when asked about releasing, or ' +\n 'when asked to fix a figure that will not release.',\n schema: { type: 'object', properties: { ...FIGURE_ID_ARG } },\n builder: async (args: any, ctx: any) => {\n const domainId = requireDomainId(ctx?.state)\n const figureId = figureIdFrom(args, ctx?.host)\n const row = await resolveFigureTarget(figureId, domainId, ctx?.host)\n if (!row) return missingFigureTarget()\n\n const current = sourceForTool(row, ctx?.host)\n const { inspectSource } = getDeps()\n /* Inspected whole, here; only what the model is told is held to its budget. */\n return { ...findingsWithinBudget(inspectSource(current.source ? JSON.stringify(current.source) : null, null, undefined, row.type)), draft: current.draft }\n }\n },\n {\n kind: 'read',\n name: 'proposeFigureCandidate',\n /* 후보 생성 — 저장은 하지 않지만 같은 문의 권한을 쓴다. */\n doors: ['Mutation.proposeFigure'],\n description:\n 'Asks for a proposal: the modeller commands that make a new figure or revise the one open in the modeller. ' +\n 'Returns the commands with the score and cost of the figure they make. NOTHING IS SAVED — the author applies ' +\n 'the proposal in the modeller as one step, or leaves it. This is the only way a proposal reaches the screen.',\n schema: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description: 'What to make or change, in the words the author used, with the sizes as they said them: do not turn sizes into axes.'\n },\n figureId: {\n type: 'string',\n description: 'Revise this figure; it must be the one open in the modeller. Omit to revise the open one; pass null to create anew.'\n },\n name: {\n type: 'string',\n description: 'The name a person reads for a new figure.'\n },\n create: {\n type: 'boolean',\n description: 'True to create rather than revise, even with a figure open.'\n },\n parts: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: the parts this change touches, read first with getFigureSource parts. Only these and the part selected may be changed; new parts may be added and fastened to any part.'\n },\n sections: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Only for a figure too large to read whole: JSON Pointers of the sections in outline.omitted this change touches, read first with getFigureSource sections. Nothing else in those sections may be changed.'\n }\n },\n required: ['prompt']\n },\n builder: async (args: any, ctx: ToolCallContext) => {\n const domainId = requireDomainId(ctx?.state)\n const prompt = typeof args?.prompt === 'string' ? args.prompt.trim() : ''\n if (!prompt) throw new Error('prompt is required: there is nothing to ask for')\n\n /*\n 고치는 것인지 만드는 것인지를 **문맥에서 정한다.** 열린 도형이 있으면 고치는 것이 기본이고,\n 모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는 도형을 덮어쓰는\n 후보가 온다.\n\n 고치는 제안은 모델러가 **요청 당시의 판(context · revision)** 위에 한 단계로 적용한다(ADR-0094).\n 그래서 고칠 수 있는 것은 모델러에 열린 도형뿐이고, 그 판을 문맥이 함께 실어 와야 한다.\n */\n const host = ctx?.host\n const create = args?.create === true || args?.figureId === null\n let base: unknown\n let figureId: string | undefined\n let focus: ReturnType<typeof focusOf> | undefined\n if (!create) {\n const said = typeof args?.figureId === 'string' ? args.figureId.trim() : ''\n const open = typeof host?.figureId === 'string' ? host.figureId.trim() : ''\n if (said && said !== open) {\n await figureInDomain(said, domainId)\n return figureNotOpen()\n }\n if (!open) return missingFigureTarget()\n const row = await resolveFigureTarget(open, domainId, host)\n if (!row) return missingFigureTarget()\n const current = sourceForTool(row, host)\n base = current.source ?? undefined\n if (!isFigure(base)) return figureNotOpen()\n if (typeof host?.context !== 'string' || !Number.isInteger(host?.revision)) return figureNotOpen()\n figureId = open\n /* \"Make this one bigger\": the part selected is what the request points at. */\n if (current.draft) focus = focusOf(host, base)\n }\n\n /*\n The pictures the person sent with this turn, as the server checked them (ADR-0061, 2026-10-16 decision 2) --\n every one, in the order attached. Never from the host context: the client fills it.\n */\n const images = (ctx?.attachments ?? [])\n .filter((file: ToolAttachment): file is ToolImageAttachment => file.kind === 'image')\n .map(file => ({ data: file.data, mediaType: file.mediaType as AIImageMediaType }))\n\n const { proposeFigureSteps } = getDeps()\n let result: any\n try {\n result = await proposeFigureSteps({\n /* The agent of this conversation's turn - the one the person picked, or the domain default. */\n client: await aiClientFor({\n domain: ctx?.state?.domain,\n user: ctx?.state?.user,\n agentId: ctx?.state?.aiAgentId,\n modeKind: ctx?.mode?.kind\n }),\n prompt,\n base,\n name: typeof args?.name === 'string' && args.name.trim() ? args.name.trim() : undefined,\n ...(images.length ? { images } : {}),\n ...(focus && Object.keys(focus).length ? { focus } : {}),\n ...(!create && (stringsOf(args?.parts).length || stringsOf(args?.sections).length)\n ? { read: { parts: stringsOf(args?.parts), sections: stringsOf(args?.sections) } }\n : {})\n })\n } catch (error) {\n /*\n * 세 번 거절된 끝의 사유를 ProposeFigureFailure.reasons 에만 두면 agentic-loop 은 「만들지 못했습니다」만\n * 받아 화면에는 「응답이 비어있습니다」가 된다. 다시 시도할 수 있는 말로 경계를 넘긴다.\n * 다른 예외(권한·통신)는 원문을 보존한다.\n */\n const reasons = Array.isArray((error as any)?.reasons) ? (error as any).reasons : []\n if (reasons.length > 0) throw new Error([(error as Error).message, ...reasons].join('\\n'))\n throw error\n }\n\n /*\n **`proposed: true` 가 카드를 만든다.** 이 표시가 없으면 제안은 도구 추적 안에 묻히고 화면에는\n 아무것도 생기지 않는다. 카드의 실행 단추가 figure-ui 의 처리기에 넘기고, 처리기가 모델러에 명령\n 목록을 한 단계로 적용한다. `args` 는 같은 제안을 두 번 세지 않기 위한 열쇠의 일부다.\n */\n const name = result.source.name || 'Figure'\n /* The card is read by a person, so the server writes it in the request's language (ADR-0061, 2026-10-16 decision 1). */\n const t = ctx.t\n return {\n proposed: true,\n /*\n The proposal's own name, given once here (ADR-0097 §5.6 item 5; AI lane, 09-27): the dock keys its card by\n it, a new figure made from it is created under it (the row id), and a save records it -- so what became of\n it can be asked after a reload, and the same proposal never makes two figures.\n */\n key: randomUUID(),\n icon: 'view_in_ar',\n label: create\n ? t('figure.proposal.label-create', { name, defaultValue: 'Make {name}' })\n : t('figure.proposal.label-revise', { name, defaultValue: 'Revise {name}' }),\n reason: t('figure.proposal.reason', {\n steps: result.steps.length,\n grade: result.score?.grade ?? '-',\n triangles: result.cost.triangles,\n attempts: result.attempts,\n defaultValue: '{steps} commands · grade {grade} · {triangles} triangles · made in {attempts} tries'\n }),\n args: { prompt, figureId, create },\n create,\n figureId,\n context: create ? undefined : host.context,\n revision: create ? undefined : host.revision,\n steps: result.steps,\n score: result.score,\n cost: result.cost,\n attempts: result.attempts\n }\n }\n }\n ] as ToolSpec[]\n}\n\n/**\n * 등록 — 부팅 시 1회.\n *\n * 범주가 하나다. twin 은 관찰과 생성을 둘로 갈랐는데(운영 협의에 생성 도구가 들려 있으면 대화의\n * 성격이 흐려진다), figure 의 대화면은 저작면 하나뿐이고 그 자리에서 읽기와 후보 요청이 함께 필요하다.\n * 대화면이 늘면 그때 가른다.\n */\nexport function registerFigureToolCategories(): void {\n const authoring: ToolCategory = {\n name: 'figure-authoring',\n description: 'Reads the source, cost and release verdict of the figure being authored, and proposes changes (nothing is saved).',\n guidance: [\n '- **For a request to make or change a figure, always call `proposeFigureCandidate`.** A proposal exists only as the result of that call.',\n ' Writing \"I made a proposal\" or \"press apply\" without the call is **false**: no card appears, and the person looks for a button that does not exist.',\n ' A proposal is a list of modeller commands. The modeller applies it as one step only when the person runs it from the dock card, and one undo takes it all back. Do not say the figure has changed before that.',\n ' A revision can be proposed only for the figure open in the modeller. Say what the result\\'s `steps` do as they are; do not invent changes the commands do not make.',\n '- Never save the source yourself. Propose; the author decides on the screen whether to take it.',\n '- In the prompt to `proposeFigureCandidate`, pass the person\\'s words as they are: their sizes, counts and names. Do not turn them into axes; the writer knows the figure\\'s axes. When you name an axis to the person, the figure\\'s Y is up.',\n '- **For a request to change a figure, call `getFigureSource` first.** Revising without reading proposes against a guess, and a renamed part breaks the bindings of the boards it is already placed on.',\n '- On the catalog nothing is open. To read an existing figure, find the id of the name or type the person said with `listFigures`; ask which figure only when it is ambiguous. To revise an existing figure, tell the person to open it in the modeller and ask there. For a new figure, do not read existing sources: call `proposeFigureCandidate` with create: true.',\n '- Do not invent type names; check them with `listFigures`. **A type name is a stored identifier**, and boards find the figure by it. A new figure\\'s type is set by a person at its first save.',\n '- When asked why a figure will not release, call `inspectFigure`. Do not say it can be released without its verdict.',\n ' Each finding carries **why it is a problem and what to change**. Pass it on as it is; a summary makes the author look again for which axis of which part to fix.',\n '- For weight or triangle counts, use `cost` from `getFigureSource`. Do not estimate.'\n ].join('\\n'),\n specs: figureToolSpecs()\n }\n\n registerToolCategory(authoring)\n}\n"]}
|