@things-factory/ai-assistant 10.1.241 → 10.1.245

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.
@@ -14,6 +14,7 @@ exports.modeScreens = modeScreens;
14
14
  /* Read by the resolver and by the boot report, so the report and the conversation open the same tools. */
15
15
  const entry_target_js_1 = require("../data-entry/entry-target.js");
16
16
  const read_target_js_1 = require("../data-read/read-target.js");
17
+ const help_keys_js_1 = require("../help-documents/help-keys.js");
17
18
  const people_keys_js_1 = require("../people/people-keys.js");
18
19
  const conversationCategories = new Map();
19
20
  function registerConversationCategory(category) {
@@ -40,6 +41,8 @@ function modeToolCategories(mode) {
40
41
  'assistant-workspace',
41
42
  /* Every conversation may read who works here and offer to bring one of them in (people/, ADR-0073 decision 3). */
42
43
  ...people_keys_js_1.PEOPLE_CATEGORIES,
44
+ /* Every conversation may read the application's help (ADR-0181). */
45
+ help_keys_js_1.HELP_CATEGORY,
43
46
  ...(mode.attachments?.kinds?.length ? ['chat-attachments'] : []),
44
47
  ...(mode.entryTargets ?? []).map(key => `data-entry:${key}`),
45
48
  ...(mode.readTargets ?? []).map(key => `data-read:${key}`),
@@ -111,6 +114,8 @@ function modeFrontCategories(mode, screen = {}) {
111
114
  * there was no tool to look people up (2026-10-24).
112
115
  */
113
116
  ...people_keys_js_1.PEOPLE_CATEGORIES,
117
+ /* Two tools, always in front: 「지출결의는 어디서 올려?」 is asked on any screen (ADR-0181). */
118
+ help_keys_js_1.HELP_CATEGORY,
114
119
  ...(mode.attachments?.kinds?.length ? ['chat-attachments'] : []),
115
120
  ...keys.filter(key => (mode.readTargets ?? []).includes(key)).map(key => `data-read:${key}`),
116
121
  ...keys.filter(key => (mode.entryTargets ?? []).includes(key)).map(key => `data-entry:${key}`),
@@ -1 +1 @@
1
- {"version":3,"file":"mode-categories.js","sourceRoot":"","sources":["../../../server/service/assistant-mode/mode-categories.ts"],"names":[],"mappings":"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","sourcesContent":["/* Read by the resolver and by the boot report, so the report and the conversation open the same tools. */\nimport { entryTargetOf } from '../data-entry/entry-target.js'\nimport { detailReadOf, readTargetOf } from '../data-read/read-target.js'\nimport { PEOPLE_CATEGORIES } from '../people/people-keys.js'\n/**\n * A category another package opens in every conversation - a dashboard card (ADR-0160 decision 9). It is in reach of\n * every conversation; it is put in front only on the pages it names, and found with `openTools` elsewhere (ADR-0061\n * decision 9). Never in an unattended run: its tools are proposals, and nobody is there to press the card.\n */\nexport interface ConversationCategory {\n name: string\n /** The application routes whose conversations put it in front (`my-dashboard`). */\n frontPages?: string[]\n /**\n * The axes of the records whose selection or anchor puts it in front (`dashboard-card`) - a card picked to change is\n * changed by this category's tools, wherever the dock is open.\n */\n frontAxes?: string[]\n /**\n * What a turn asked from one of its front pages must end in - said in that turn's system prompt only. On 나의 대시보드\n * a request to see a figure is a card; asked 「이번 달 지출 합계」 there, the model answered 「0원」 in words (2026-10-25).\n */\n pageRule?: string\n}\n\nconst conversationCategories = new Map<string, ConversationCategory>()\n\nexport function registerConversationCategory(category: ConversationCategory): void {\n conversationCategories.set(category.name, category)\n}\n\nexport function conversationCategoriesOf(): ConversationCategory[] {\n return [...conversationCategories.values()]\n}\n\nexport function clearConversationCategories(): void {\n conversationCategories.clear()\n}\n\n/** The system prompt of one turn - the mode's, the open record's line, and the rules of the page it is asked from. */\nexport function turnSystemPrompt(modePrompt: string, screen: { page?: string; subjectLine?: string } = {}): string {\n const pageRules = screen.page ? conversationCategoriesOf().filter(one => one.pageRule && (one.frontPages ?? []).includes(screen.page!)).map(one => one.pageRule!) : []\n return [modePrompt, screen.subjectLine, ...pageRules].filter(Boolean).join('\\n\\n')\n}\n\n/**\n * The categories a mode opens: its own, the AI 작업 패널 (design/ai/workspace.md), the attachment reader when it\n * takes files (design/ai/shared-dock.md §9-4), and one propose tool per record it may enter (design/ai/data-entry.md).\n */\nexport function modeToolCategories(mode: { toolCategories?: string[]; attachments?: { kinds?: string[] }; entryTargets?: string[]; readTargets?: string[] }): string[] | undefined {\n const extra = [\n /* Every conversation may put a large result on the AI 작업 패널 (design/ai/workspace.md). */\n 'assistant-workspace',\n /* Every conversation may read who works here and offer to bring one of them in (people/, ADR-0073 decision 3). */\n ...PEOPLE_CATEGORIES,\n ...(mode.attachments?.kinds?.length ? ['chat-attachments'] : []),\n ...(mode.entryTargets ?? []).map(key => `data-entry:${key}`),\n ...(mode.readTargets ?? []).map(key => `data-read:${key}`),\n ...conversationCategoriesOf().map(one => one.name)\n ]\n return [...new Set([...(mode.toolCategories ?? []), ...extra])]\n}\n\n/**\n * The categories an unattended run of a mode opens: its own and the lists it reads (design/ai/unattended-run.md §3).\n *\n * Not the 입력안 tools - nobody is there to press the card - nor the AI 작업 패널 or the attachment reader: there is no\n * conversation for a card or a file to belong to.\n */\nexport function unattendedToolCategories(mode: { toolCategories?: string[]; readTargets?: string[] }): string[] {\n return [...new Set([...(mode.toolCategories ?? []), ...(mode.readTargets ?? []).map(key => `data-read:${key}`)])]\n}\n\n/** The screen a turn is asked from - the page the dock is on, and the record its conversation is anchored to. */\nexport interface TurnScreen {\n /** The application's route of the open page (`cash-transaction-list`), as the dock sends it. */\n page?: string\n /** The axis of the record the conversation is anchored to (`contract` of `subject` · `contract:<id>`), from the stored anchor. */\n subjectAxis?: string\n /** The axes of the records the latest selection named (`contract` of `[keys] contracts contract:<id>`) - `selectionAxesOf`. */\n selectionAxes?: string[]\n}\n\n/** The line of a selection note the model reads - the client's `SELECTION_KEYS_PREFIX` (assistant-selection.ts). */\nexport const SELECTION_KEYS_LINE = '[keys]'\n\n/**\n * The axes of the records the latest selection note names (「AI와 작업」, shared-dock §2-11-1): a list hands its rows as\n * `<axis>:<uuid>`, so the rows' list is read with the tool of that axis. Put in front like an anchored record's - picked\n * on 미수금, the contracts' read was not in front, and the model looked for them among attachments and a dashboard's cards\n * before it opened the right tool (2026-10-25). A note is the server's (`appendSessionNote`, system); a person's words\n * are never read for it.\n */\nexport function selectionAxesOf(rows: { role?: string; content?: string | null }[]): string[] {\n for (let i = rows.length - 1; i >= 0; i--) {\n if (rows[i].role !== 'system') continue\n const line = String(rows[i].content ?? '')\n .split('\\n')\n .find(one => one.startsWith(SELECTION_KEYS_LINE))\n if (!line) continue\n const keys = line.slice(SELECTION_KEYS_LINE.length).trim().split(/\\s+/)\n return [...new Set(keys.map(one => one.match(/^([a-z0-9-]+):/)?.[1]).filter((one): one is string => !!one))]\n }\n return []\n}\n\ntype FrontMode = { toolCategories?: string[]; attachments?: { kinds?: string[] }; entryTargets?: string[]; readTargets?: string[] }\n\n/**\n * The records the open screen is about, among those the mode reads and enters (ADR-0061 decision 9). Nothing new is\n * declared: a read target's screen route is the page that lists it, and a key's last part is the axis of its record\n * (`office.contract` is the record of the axis `contract`) - reading and entering one record share its key.\n */\nexport function screenTargetKeys(mode: FrontMode, screen: TurnScreen, routeOf: (key: string) => string | undefined = key => readTargetOf(key)?.screen?.route): string[] {\n const keys = [...new Set([...(mode.readTargets ?? []), ...(mode.entryTargets ?? [])])]\n return keys.filter(\n key =>\n (!!screen.page && routeOf(key) === screen.page) ||\n (!!screen.subjectAxis && axesOfKey(mode, key).includes(screen.subjectAxis)) ||\n (!!screen.selectionAxes?.length && axesOfKey(mode, key).some(axis => screen.selectionAxes!.includes(axis)))\n )\n}\n\n/** The records a key is about: its last part, and the axes a card joins or a whole answer covers (EntryTarget.axes · DetailRead.axes). */\nfunction axesOfKey(mode: FrontMode, key: string): string[] {\n const card = (mode.entryTargets ?? []).includes(key) ? entryTargetOf(key)?.axes ?? [] : []\n const answer = (mode.readTargets ?? []).includes(key) ? detailReadOf(key)?.axes ?? [] : []\n return [key.split('.').pop()!, ...card, ...answer]\n}\n\n/**\n * The categories a turn puts in front when the mode's tools do not fit in one call: the mode's own, the AI 작업 패널, the\n * people list and the invite card, the attachment reader, and the open screen's records. The rest the model opens with `openTools`.\n */\nexport function modeFrontCategories(mode: FrontMode, screen: TurnScreen = {}): string[] {\n const keys = screenTargetKeys(mode, screen)\n return [\n ...new Set([\n ...(mode.toolCategories ?? []),\n 'assistant-workspace',\n /*\n * Two tools, always in front: 「정연희 초대해 줘」 asked in a conversation whose tools did not fit got the answer that\n * there was no tool to look people up (2026-10-24).\n */\n ...PEOPLE_CATEGORIES,\n ...(mode.attachments?.kinds?.length ? ['chat-attachments'] : []),\n ...keys.filter(key => (mode.readTargets ?? []).includes(key)).map(key => `data-read:${key}`),\n ...keys.filter(key => (mode.entryTargets ?? []).includes(key)).map(key => `data-entry:${key}`),\n ...conversationCategoriesOf()\n .filter(one => (!!screen.page && (one.frontPages ?? []).includes(screen.page)) || (one.frontAxes ?? []).some(axis => axis === screen.subjectAxis || !!screen.selectionAxes?.includes(axis)))\n .map(one => one.name)\n ])\n ]\n}\n\n/** Each screen the mode could be asked from - a page that lists one of its records, a record's axis - for the boot report. */\nexport function modeScreens(mode: FrontMode, routeOf: (key: string) => string | undefined = key => readTargetOf(key)?.screen?.route): TurnScreen[] {\n const keys = [...new Set([...(mode.readTargets ?? []), ...(mode.entryTargets ?? [])])]\n const pages = [...new Set([...keys.map(routeOf), ...conversationCategoriesOf().flatMap(one => one.frontPages ?? [])].filter(Boolean) as string[])]\n const axes = [...new Set(keys.flatMap(key => axesOfKey(mode, key)))]\n return [{}, ...pages.map(page => ({ page })), ...axes.map(subjectAxis => ({ subjectAxis }))]\n}\n"]}
1
+ {"version":3,"file":"mode-categories.js","sourceRoot":"","sources":["../../../server/service/assistant-mode/mode-categories.ts"],"names":[],"mappings":"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","sourcesContent":["/* Read by the resolver and by the boot report, so the report and the conversation open the same tools. */\nimport { entryTargetOf } from '../data-entry/entry-target.js'\nimport { detailReadOf, readTargetOf } from '../data-read/read-target.js'\nimport { HELP_CATEGORY } from '../help-documents/help-keys.js'\nimport { PEOPLE_CATEGORIES } from '../people/people-keys.js'\n/**\n * A category another package opens in every conversation - a dashboard card (ADR-0160 decision 9). It is in reach of\n * every conversation; it is put in front only on the pages it names, and found with `openTools` elsewhere (ADR-0061\n * decision 9). Never in an unattended run: its tools are proposals, and nobody is there to press the card.\n */\nexport interface ConversationCategory {\n name: string\n /** The application routes whose conversations put it in front (`my-dashboard`). */\n frontPages?: string[]\n /**\n * The axes of the records whose selection or anchor puts it in front (`dashboard-card`) - a card picked to change is\n * changed by this category's tools, wherever the dock is open.\n */\n frontAxes?: string[]\n /**\n * What a turn asked from one of its front pages must end in - said in that turn's system prompt only. On 나의 대시보드\n * a request to see a figure is a card; asked 「이번 달 지출 합계」 there, the model answered 「0원」 in words (2026-10-25).\n */\n pageRule?: string\n}\n\nconst conversationCategories = new Map<string, ConversationCategory>()\n\nexport function registerConversationCategory(category: ConversationCategory): void {\n conversationCategories.set(category.name, category)\n}\n\nexport function conversationCategoriesOf(): ConversationCategory[] {\n return [...conversationCategories.values()]\n}\n\nexport function clearConversationCategories(): void {\n conversationCategories.clear()\n}\n\n/** The system prompt of one turn - the mode's, the open record's line, and the rules of the page it is asked from. */\nexport function turnSystemPrompt(modePrompt: string, screen: { page?: string; subjectLine?: string } = {}): string {\n const pageRules = screen.page ? conversationCategoriesOf().filter(one => one.pageRule && (one.frontPages ?? []).includes(screen.page!)).map(one => one.pageRule!) : []\n return [modePrompt, screen.subjectLine, ...pageRules].filter(Boolean).join('\\n\\n')\n}\n\n/**\n * The categories a mode opens: its own, the AI 작업 패널 (design/ai/workspace.md), the attachment reader when it\n * takes files (design/ai/shared-dock.md §9-4), and one propose tool per record it may enter (design/ai/data-entry.md).\n */\nexport function modeToolCategories(mode: { toolCategories?: string[]; attachments?: { kinds?: string[] }; entryTargets?: string[]; readTargets?: string[] }): string[] | undefined {\n const extra = [\n /* Every conversation may put a large result on the AI 작업 패널 (design/ai/workspace.md). */\n 'assistant-workspace',\n /* Every conversation may read who works here and offer to bring one of them in (people/, ADR-0073 decision 3). */\n ...PEOPLE_CATEGORIES,\n /* Every conversation may read the application's help (ADR-0181). */\n HELP_CATEGORY,\n ...(mode.attachments?.kinds?.length ? ['chat-attachments'] : []),\n ...(mode.entryTargets ?? []).map(key => `data-entry:${key}`),\n ...(mode.readTargets ?? []).map(key => `data-read:${key}`),\n ...conversationCategoriesOf().map(one => one.name)\n ]\n return [...new Set([...(mode.toolCategories ?? []), ...extra])]\n}\n\n/**\n * The categories an unattended run of a mode opens: its own and the lists it reads (design/ai/unattended-run.md §3).\n *\n * Not the 입력안 tools - nobody is there to press the card - nor the AI 작업 패널 or the attachment reader: there is no\n * conversation for a card or a file to belong to.\n */\nexport function unattendedToolCategories(mode: { toolCategories?: string[]; readTargets?: string[] }): string[] {\n return [...new Set([...(mode.toolCategories ?? []), ...(mode.readTargets ?? []).map(key => `data-read:${key}`)])]\n}\n\n/** The screen a turn is asked from - the page the dock is on, and the record its conversation is anchored to. */\nexport interface TurnScreen {\n /** The application's route of the open page (`cash-transaction-list`), as the dock sends it. */\n page?: string\n /** The axis of the record the conversation is anchored to (`contract` of `subject` · `contract:<id>`), from the stored anchor. */\n subjectAxis?: string\n /** The axes of the records the latest selection named (`contract` of `[keys] contracts contract:<id>`) - `selectionAxesOf`. */\n selectionAxes?: string[]\n}\n\n/** The line of a selection note the model reads - the client's `SELECTION_KEYS_PREFIX` (assistant-selection.ts). */\nexport const SELECTION_KEYS_LINE = '[keys]'\n\n/**\n * The axes of the records the latest selection note names (「AI와 작업」, shared-dock §2-11-1): a list hands its rows as\n * `<axis>:<uuid>`, so the rows' list is read with the tool of that axis. Put in front like an anchored record's - picked\n * on 미수금, the contracts' read was not in front, and the model looked for them among attachments and a dashboard's cards\n * before it opened the right tool (2026-10-25). A note is the server's (`appendSessionNote`, system); a person's words\n * are never read for it.\n */\nexport function selectionAxesOf(rows: { role?: string; content?: string | null }[]): string[] {\n for (let i = rows.length - 1; i >= 0; i--) {\n if (rows[i].role !== 'system') continue\n const line = String(rows[i].content ?? '')\n .split('\\n')\n .find(one => one.startsWith(SELECTION_KEYS_LINE))\n if (!line) continue\n const keys = line.slice(SELECTION_KEYS_LINE.length).trim().split(/\\s+/)\n return [...new Set(keys.map(one => one.match(/^([a-z0-9-]+):/)?.[1]).filter((one): one is string => !!one))]\n }\n return []\n}\n\ntype FrontMode = { toolCategories?: string[]; attachments?: { kinds?: string[] }; entryTargets?: string[]; readTargets?: string[] }\n\n/**\n * The records the open screen is about, among those the mode reads and enters (ADR-0061 decision 9). Nothing new is\n * declared: a read target's screen route is the page that lists it, and a key's last part is the axis of its record\n * (`office.contract` is the record of the axis `contract`) - reading and entering one record share its key.\n */\nexport function screenTargetKeys(mode: FrontMode, screen: TurnScreen, routeOf: (key: string) => string | undefined = key => readTargetOf(key)?.screen?.route): string[] {\n const keys = [...new Set([...(mode.readTargets ?? []), ...(mode.entryTargets ?? [])])]\n return keys.filter(\n key =>\n (!!screen.page && routeOf(key) === screen.page) ||\n (!!screen.subjectAxis && axesOfKey(mode, key).includes(screen.subjectAxis)) ||\n (!!screen.selectionAxes?.length && axesOfKey(mode, key).some(axis => screen.selectionAxes!.includes(axis)))\n )\n}\n\n/** The records a key is about: its last part, and the axes a card joins or a whole answer covers (EntryTarget.axes · DetailRead.axes). */\nfunction axesOfKey(mode: FrontMode, key: string): string[] {\n const card = (mode.entryTargets ?? []).includes(key) ? entryTargetOf(key)?.axes ?? [] : []\n const answer = (mode.readTargets ?? []).includes(key) ? detailReadOf(key)?.axes ?? [] : []\n return [key.split('.').pop()!, ...card, ...answer]\n}\n\n/**\n * The categories a turn puts in front when the mode's tools do not fit in one call: the mode's own, the AI 작업 패널, the\n * people list and the invite card, the attachment reader, and the open screen's records. The rest the model opens with `openTools`.\n */\nexport function modeFrontCategories(mode: FrontMode, screen: TurnScreen = {}): string[] {\n const keys = screenTargetKeys(mode, screen)\n return [\n ...new Set([\n ...(mode.toolCategories ?? []),\n 'assistant-workspace',\n /*\n * Two tools, always in front: 「정연희 초대해 줘」 asked in a conversation whose tools did not fit got the answer that\n * there was no tool to look people up (2026-10-24).\n */\n ...PEOPLE_CATEGORIES,\n /* Two tools, always in front: 「지출결의는 어디서 올려?」 is asked on any screen (ADR-0181). */\n HELP_CATEGORY,\n ...(mode.attachments?.kinds?.length ? ['chat-attachments'] : []),\n ...keys.filter(key => (mode.readTargets ?? []).includes(key)).map(key => `data-read:${key}`),\n ...keys.filter(key => (mode.entryTargets ?? []).includes(key)).map(key => `data-entry:${key}`),\n ...conversationCategoriesOf()\n .filter(one => (!!screen.page && (one.frontPages ?? []).includes(screen.page)) || (one.frontAxes ?? []).some(axis => axis === screen.subjectAxis || !!screen.selectionAxes?.includes(axis)))\n .map(one => one.name)\n ])\n ]\n}\n\n/** Each screen the mode could be asked from - a page that lists one of its records, a record's axis - for the boot report. */\nexport function modeScreens(mode: FrontMode, routeOf: (key: string) => string | undefined = key => readTargetOf(key)?.screen?.route): TurnScreen[] {\n const keys = [...new Set([...(mode.readTargets ?? []), ...(mode.entryTargets ?? [])])]\n const pages = [...new Set([...keys.map(routeOf), ...conversationCategoriesOf().flatMap(one => one.frontPages ?? [])].filter(Boolean) as string[])]\n const axes = [...new Set(keys.flatMap(key => axesOfKey(mode, key)))]\n return [{}, ...pages.map(page => ({ page })), ...axes.map(subjectAxis => ({ subjectAxis }))]\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare const HELP_CATEGORY = "help-documents";
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HELP_CATEGORY = void 0;
4
+ /* The help tools' category - every conversation carries it (mode-categories.ts), so it is named apart from the tools. */
5
+ exports.HELP_CATEGORY = 'help-documents';
6
+ //# sourceMappingURL=help-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-keys.js","sourceRoot":"","sources":["../../../server/service/help-documents/help-keys.ts"],"names":[],"mappings":";;;AAAA,yHAAyH;AAC5G,QAAA,aAAa,GAAG,gBAAgB,CAAA","sourcesContent":["/* The help tools' category - every conversation carries it (mode-categories.ts), so it is named apart from the tools. */\nexport const HELP_CATEGORY = 'help-documents'\n"]}
@@ -0,0 +1,38 @@
1
+ import { type ToolCategory } from '@things-factory/ai-client-base';
2
+ /** Where a part opens in the application - the help page at that part. */
3
+ export declare const helpLink: (topic: string, section?: string) => string;
4
+ export declare function searchHelpDocuments(args: {
5
+ query?: string;
6
+ limit?: number;
7
+ }, context?: any): {
8
+ found: number;
9
+ parts: any[];
10
+ message: string;
11
+ } | {
12
+ found: number;
13
+ parts: {
14
+ topic: string;
15
+ section: string;
16
+ title: string;
17
+ summary: string;
18
+ link: string;
19
+ }[];
20
+ message?: undefined;
21
+ };
22
+ export declare function readHelpDocument(args: {
23
+ topic?: string;
24
+ section?: string;
25
+ }, context?: any): {
26
+ found: boolean;
27
+ message: string;
28
+ } | {
29
+ link: string;
30
+ topic: string;
31
+ section: string;
32
+ title: string;
33
+ documentTitle: string;
34
+ text: string;
35
+ found: boolean;
36
+ message?: undefined;
37
+ };
38
+ export declare const helpCategory: ToolCategory;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.helpCategory = exports.helpLink = void 0;
4
+ exports.searchHelpDocuments = searchHelpDocuments;
5
+ exports.readHelpDocument = readHelpDocument;
6
+ /*
7
+ * The application's help documents, for the assistant (ADR-0181) - the same index the screen's `?` asks
8
+ * (@things-factory/help). How to do a piece of work, which screen it is on, what a word means: the model finds the part
9
+ * and reads it, rather than the mode's prompt carrying the manual.
10
+ *
11
+ * The help is no one's secret - every screen's `?` opens it for whoever is there - so the tools reach no door. Whether
12
+ * the person may open the screen a part names is still that screen's own door.
13
+ */
14
+ const ai_client_base_1 = require("@things-factory/ai-client-base");
15
+ const help_1 = require("@things-factory/help");
16
+ const help_keys_js_1 = require("./help-keys.js");
17
+ /** Where a part opens in the application - the help page at that part. */
18
+ const helpLink = (topic, section = '') => `help?topic=${encodeURIComponent(topic)}${section ? `&section=${encodeURIComponent(section)}` : ''}`;
19
+ exports.helpLink = helpLink;
20
+ const languageOf = (context) => context?.state?.lng || context?.state?.language || undefined;
21
+ function searchHelpDocuments(args, context) {
22
+ const query = String(args?.query ?? '').trim();
23
+ if (!query)
24
+ return { found: 0, parts: [], message: 'name what to look for.' };
25
+ const parts = (0, help_1.searchHelp)(query, { lang: languageOf(context), limit: Math.min(Math.max(Number(args?.limit) || 5, 1), 10) }).map(hit => ({
26
+ topic: hit.topic,
27
+ section: hit.section,
28
+ title: hit.documentTitle === hit.title ? hit.title : `${hit.documentTitle} › ${hit.title}`,
29
+ summary: hit.summary,
30
+ link: (0, exports.helpLink)(hit.topic, hit.section)
31
+ }));
32
+ return parts.length ? { found: parts.length, parts } : { found: 0, parts: [], message: 'the help has nothing on this - say so; do not answer from general knowledge as if it were this application.' };
33
+ }
34
+ function readHelpDocument(args, context) {
35
+ const topic = String(args?.topic ?? '').trim();
36
+ const section = String(args?.section ?? '').trim();
37
+ const part = topic ? (0, help_1.readHelp)(topic, section, languageOf(context)) : null;
38
+ if (!part)
39
+ return { found: false, message: `no help part ${topic}${section ? `#${section}` : ''} - search again with searchHelp.` };
40
+ return { found: true, ...part, link: (0, exports.helpLink)(part.topic, part.section) };
41
+ }
42
+ const searchSpec = {
43
+ kind: 'read',
44
+ name: 'searchHelp',
45
+ doors: [],
46
+ description: "Search this application's help and manuals (how to do a piece of work, which screen and menu it is on, what a term means). " +
47
+ 'Returns the matching parts with a one-line summary and a link; read one with readHelp.',
48
+ schema: {
49
+ type: 'object',
50
+ properties: {
51
+ query: { type: 'string', description: 'The words to look for, in the language of the help - a screen or menu name, a task, a term ("지출결의 지급", "휴가 신청").' },
52
+ limit: { type: 'number', description: 'How many parts, 1-10. Default 5.' }
53
+ },
54
+ required: ['query']
55
+ },
56
+ builder: (args, context) => searchHelpDocuments(args, context)
57
+ };
58
+ const readSpec = {
59
+ kind: 'read',
60
+ name: 'readHelp',
61
+ doors: [],
62
+ description: 'Read one part of the help (topic and section from searchHelp), or the whole document when section is left out.',
63
+ schema: {
64
+ type: 'object',
65
+ properties: {
66
+ topic: { type: 'string', description: 'The topic from searchHelp ("office/guide-employee").' },
67
+ section: { type: 'string', description: 'The section from searchHelp ("leave"). Leave out for the whole document.' }
68
+ },
69
+ required: ['topic']
70
+ },
71
+ builder: (args, context) => readHelpDocument(args, context)
72
+ };
73
+ exports.helpCategory = {
74
+ name: help_keys_js_1.HELP_CATEGORY,
75
+ description: "the application's help and manuals",
76
+ guidance: [
77
+ '- When the person asks how to do something in this application, where a screen or menu is, what the steps are, or what a term on a screen means, call searchHelp, then readHelp on the part that answers it - before you answer.',
78
+ '- Answer from what readHelp returned, in your own short words, and end with the part as a link: [its title](its link). Never invent a menu, a button or a step the help does not name.',
79
+ '- When searchHelp finds nothing, say the help does not cover it; then answer only what your other tools show.',
80
+ '- The help says how the application works; figures and records still come from the other tools.'
81
+ ].join('\n'),
82
+ specs: [searchSpec, readSpec]
83
+ };
84
+ (0, ai_client_base_1.registerToolCategory)(exports.helpCategory);
85
+ //# sourceMappingURL=help-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-tools.js","sourceRoot":"","sources":["../../../server/service/help-documents/help-tools.ts"],"names":[],"mappings":";;;AAkBA,kDAWC;AAED,4CAMC;AArCD;;;;;;;GAOG;AACH,mEAAuG;AACvG,+CAA2D;AAE3D,iDAA8C;AAE9C,0EAA0E;AACnE,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CAAC,cAAc,kBAAkB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AAAhJ,QAAA,QAAQ,YAAwI;AAE7J,MAAM,UAAU,GAAG,CAAC,OAAY,EAAsB,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,OAAO,EAAE,KAAK,EAAE,QAAQ,IAAI,SAAS,CAAA;AAErH,SAAgB,mBAAmB,CAAC,IAAwC,EAAE,OAAa;IACzF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAA;IAC7E,MAAM,KAAK,GAAG,IAAA,iBAAU,EAAC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrI,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,aAAa,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,aAAa,MAAM,GAAG,CAAC,KAAK,EAAE;QAC1F,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,IAAI,EAAE,IAAA,gBAAQ,EAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;KACvC,CAAC,CAAC,CAAA;IACH,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,6GAA6G,EAAE,CAAA;AACxM,CAAC;AAED,SAAgB,gBAAgB,CAAC,IAA0C,EAAE,OAAa;IACxF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAClD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAA,eAAQ,EAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACzE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,kCAAkC,EAAE,CAAA;IACnI,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAA,gBAAQ,EAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;AAC3E,CAAC;AAED,MAAM,UAAU,GAAG;IACjB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,EAAE;IACT,WAAW,EACT,6HAA6H;QAC7H,wFAAwF;IAC1F,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kHAAkH,EAAE;YAC1J,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;SAC3E;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB;IACD,OAAO,EAAE,CAAC,IAAS,EAAE,OAAY,EAAE,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC;CAC7D,CAAA;AAEb,MAAM,QAAQ,GAAG;IACf,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,gHAAgH;IAC7H,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sDAAsD,EAAE;YAC9F,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0EAA0E,EAAE;SACrH;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB;IACD,OAAO,EAAE,CAAC,IAAS,EAAE,OAAY,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC;CAC1D,CAAA;AAEA,QAAA,YAAY,GAAiB;IACxC,IAAI,EAAE,4BAAa;IACnB,WAAW,EAAE,oCAAoC;IACjD,QAAQ,EAAE;QACR,kOAAkO;QAClO,wLAAwL;QACxL,+GAA+G;QAC/G,iGAAiG;KAClG,CAAC,IAAI,CAAC,IAAI,CAAC;IACZ,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC;CAC9B,CAAA;AAED,IAAA,qCAAoB,EAAC,oBAAY,CAAC,CAAA","sourcesContent":["/*\n * The application's help documents, for the assistant (ADR-0181) - the same index the screen's `?` asks\n * (@things-factory/help). How to do a piece of work, which screen it is on, what a word means: the model finds the part\n * and reads it, rather than the mode's prompt carrying the manual.\n *\n * The help is no one's secret - every screen's `?` opens it for whoever is there - so the tools reach no door. Whether\n * the person may open the screen a part names is still that screen's own door.\n */\nimport { registerToolCategory, type ToolCategory, type ToolSpec } from '@things-factory/ai-client-base'\nimport { readHelp, searchHelp } from '@things-factory/help'\n\nimport { HELP_CATEGORY } from './help-keys.js'\n\n/** Where a part opens in the application - the help page at that part. */\nexport const helpLink = (topic: string, section = '') => `help?topic=${encodeURIComponent(topic)}${section ? `&section=${encodeURIComponent(section)}` : ''}`\n\nconst languageOf = (context: any): string | undefined => context?.state?.lng || context?.state?.language || undefined\n\nexport function searchHelpDocuments(args: { query?: string; limit?: number }, context?: any) {\n const query = String(args?.query ?? '').trim()\n if (!query) return { found: 0, parts: [], message: 'name what to look for.' }\n const parts = searchHelp(query, { lang: languageOf(context), limit: Math.min(Math.max(Number(args?.limit) || 5, 1), 10) }).map(hit => ({\n topic: hit.topic,\n section: hit.section,\n title: hit.documentTitle === hit.title ? hit.title : `${hit.documentTitle} › ${hit.title}`,\n summary: hit.summary,\n link: helpLink(hit.topic, hit.section)\n }))\n return parts.length ? { found: parts.length, parts } : { found: 0, parts: [], message: 'the help has nothing on this - say so; do not answer from general knowledge as if it were this application.' }\n}\n\nexport function readHelpDocument(args: { topic?: string; section?: string }, context?: any) {\n const topic = String(args?.topic ?? '').trim()\n const section = String(args?.section ?? '').trim()\n const part = topic ? readHelp(topic, section, languageOf(context)) : null\n if (!part) return { found: false, message: `no help part ${topic}${section ? `#${section}` : ''} - search again with searchHelp.` }\n return { found: true, ...part, link: helpLink(part.topic, part.section) }\n}\n\nconst searchSpec = {\n kind: 'read',\n name: 'searchHelp',\n doors: [],\n description:\n \"Search this application's help and manuals (how to do a piece of work, which screen and menu it is on, what a term means). \" +\n 'Returns the matching parts with a one-line summary and a link; read one with readHelp.',\n schema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'The words to look for, in the language of the help - a screen or menu name, a task, a term (\"지출결의 지급\", \"휴가 신청\").' },\n limit: { type: 'number', description: 'How many parts, 1-10. Default 5.' }\n },\n required: ['query']\n },\n builder: (args: any, context: any) => searchHelpDocuments(args, context)\n} as ToolSpec\n\nconst readSpec = {\n kind: 'read',\n name: 'readHelp',\n doors: [],\n description: 'Read one part of the help (topic and section from searchHelp), or the whole document when section is left out.',\n schema: {\n type: 'object',\n properties: {\n topic: { type: 'string', description: 'The topic from searchHelp (\"office/guide-employee\").' },\n section: { type: 'string', description: 'The section from searchHelp (\"leave\"). Leave out for the whole document.' }\n },\n required: ['topic']\n },\n builder: (args: any, context: any) => readHelpDocument(args, context)\n} as ToolSpec\n\nexport const helpCategory: ToolCategory = {\n name: HELP_CATEGORY,\n description: \"the application's help and manuals\",\n guidance: [\n '- When the person asks how to do something in this application, where a screen or menu is, what the steps are, or what a term on a screen means, call searchHelp, then readHelp on the part that answers it - before you answer.',\n '- Answer from what readHelp returned, in your own short words, and end with the part as a link: [its title](its link). Never invent a menu, a button or a step the help does not name.',\n '- When searchHelp finds nothing, say the help does not cover it; then answer only what your other tools show.',\n '- The help says how the application works; figures and records still come from the other tools.'\n ].join('\\n'),\n specs: [searchSpec, readSpec]\n}\n\nregisterToolCategory(helpCategory)\n"]}
@@ -11,6 +11,7 @@ import './chat-session/session-purge.js';
11
11
  import './chat-session/attachment-route.js';
12
12
  import { EntryProposalResolver } from './data-entry/entry-resolver.js';
13
13
  import './workspace/workspace-tools.js';
14
+ import './help-documents/help-tools.js';
14
15
  import './people/index.js';
15
16
  export * from './types.js';
16
17
  export * from './chat-session-resolver.js';
@@ -18,6 +18,7 @@ require("./chat-session/session-purge.js");
18
18
  require("./chat-session/attachment-route.js");
19
19
  const entry_resolver_js_1 = require("./data-entry/entry-resolver.js");
20
20
  require("./workspace/workspace-tools.js");
21
+ require("./help-documents/help-tools.js");
21
22
  /* Who works here, and the card that brings one of them into a conversation - every conversation carries both. */
22
23
  require("./people/index.js");
23
24
  const index_js_4 = require("./unattended-run/index.js");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yEAAgE;AAChE,6EAAoE;AACpE,4FAAmF;AACnF,yFAAgF;AAChF,iEAAwD;AACxD,sGAA+F;AAC/F,8FAAqF;AACrF,4FAAmF;AACnF,sDAAyE;AACzE,sDAAyE;AACzE,kEAAgG;AAChG,8CAA2C;AAC3C,2CAAwC;AACxC,8CAA2C;AAC3C,sEAAsE;AACtE,0CAAuC;AACvC,iHAAiH;AACjH,6BAA0B;AAC1B,wDAA6E;AAE7E,qDAA0B;AAC1B,qEAA0C;AAC1C,uEAA4C;AAC5C,oGAAoG;AACpG,oEAAyC;AACzC,iEAA2D;AAAlD,0HAAA,iBAAiB,OAAA;AAC1B,6EAAkD;AAClD;;;GAGG;AACH,2DAAgC;AAChC,+GAA+G;AAC/G,uEAA4C;AAC5C,8DAA+F;AAAtF,qHAAA,mBAAmB,OAAA;AAAE,iHAAA,eAAe,OAAA;AAAE,6GAAA,WAAW,OAAA;AAC1D,yHAAyH;AACzH,gEAA0E;AAAjE,iHAAA,cAAc,OAAA;AAAE,8GAAA,WAAW,OAAA;AACpC,uHAAuH;AACvH,qEAA0C;AAC1C,2DAA+I;AAAtI,mHAAA,kBAAkB,OAAA;AAAE,+GAAA,cAAc,OAAA;AAAE,mHAAA,kBAAkB,OAAA;AAAE,iHAAA,gBAAgB,OAAA;AAAE,0GAAA,SAAS,OAAA;AAC5F,mEAAwC;AACxC,4DAAiC;AACjC,mFAAmF;AACnF,0EAA+C;AAC/C,gDAAgD;AAChD,iEAAsC;AACtC,sDAAsD;AACtD,2EAAgD;AAChD,gHAAgH;AAChH,+EAAoD;AACpD,kEAAuC;AACvC,8DAA8D;AAC9D,0EAA+C;AAC/C,8EAAmD;AACnD,0EAA+C;AAC/C,qFAA0D;AAC1D,uFAA4D;AAC5D,wEAA6C;AAC7C,4EAAiD;AACjD,yEAA8C;AAC9C,wDAAwD;AACxD,iFAAsD;AACtD,iFAAsD;AACtD,mFAAwD;AACxD,4FAAiE;AACjE,2DAA2D;AAC3D,uFAA4D;AAC5D,iFAAsD;AACtD,kEAAuC;AACvC,8EAAmD;AACnD,gJAAgJ;AAChJ,0EAA4E;AAAnE,8HAAA,uBAAuB,OAAA;AAChC,8EAA4E;AAAnE,8HAAA,qBAAqB,OAAA;AAC9B,4GAA4G;AAC5G,oEAAyC;AAE5B,QAAA,QAAQ,GAAG,CAAC,GAAG,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,GAAG,mBAA8B,EAAE,GAAG,mBAAqB,CAAC,CAAA;AAExH,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,8CAAmB;QACnB,sDAAsD;QACtD,kDAAqB;QACrB,uDAAuD;QACvD,kDAAqB;QACrB,wDAAwD;QACxD,8DAA2B;QAC3B,mGAAmG;QACnG,sCAAe;QACf,sDAAuB;QACvB,wDAAwD;QACxD,oDAAsB;QACtB,qDAAqD;QACrD,gEAA6B;QAC7B,mDAAmD;QACnD,yCAAqB;KACtB;CACF,CAAA","sourcesContent":["import { ChatSessionResolver } from './chat-session-resolver.js'\nimport { AssistantChatResolver } from './assistant-chat-resolver.js'\nimport { AssistantModeResolver } from './assistant-mode/assistant-mode-resolver.js'\nimport { AssistantCapabilityResolver } from './assistant-capability-resolver.js'\nimport { AiAgentResolver } from './ai-agent-resolver.js'\nimport { MySessionActivitySubscription } from './chat-session/session-activity-subscription.js'\nimport { ChatMessageSubscription } from './chat-message/chat-message-subscription.js'\nimport { ChatTypingSubscription } from './chat-message/chat-typing-subscription.js'\nimport { entities as ChatSessionEntities } from './chat-session/index.js'\nimport { entities as ChatMessageEntities } from './chat-message/index.js'\nimport { entities as ChatSessionParticipantEntities } from './chat-session-participant/index.js'\nimport './chat-session/attachment-tools.js'\nimport './chat-session/session-purge.js'\nimport './chat-session/attachment-route.js'\nimport { EntryProposalResolver } from './data-entry/entry-resolver.js'\nimport './workspace/workspace-tools.js'\n/* Who works here, and the card that brings one of them into a conversation - every conversation carries both. */\nimport './people/index.js'\nimport { entities as UnattendedRunEntities } from './unattended-run/index.js'\n\nexport * from './types.js'\nexport * from './chat-session-resolver.js'\nexport * from './assistant-chat-resolver.js'\n/* The mode registry — each app server declares what its conversations are (ADR-0061 decision 7). */\nexport * from './assistant-mode/index.js'\nexport { requestTranslator } from './request-translator.js'\nexport * from './assistant-capability-resolver.js'\n/*\n * 대화 각본 하네스는 **런타임 export 에서 뺀다**(ADR-0070 A15 결정 ④) — 시험 도구가 서버 번들에\n * 실린다. 시험은 경로로 가져온다: `…/service/testing/conversation-script.js`.\n */\nexport * from './tool-access.js'\n/* Data entry from material - an app registers what it can enter; a mode names it (design/ai/data-entry.md). */\nexport * from './data-entry/entry-target.js'\nexport { registerEntryTarget, entryCategoryOf, runAsCaller } from './data-entry/entry-tools.js'\n/* An application's tool that prepares many changes at once makes the same change card the model's would (2026-10-24). */\nexport { proposeChanges, MAX_CHANGES } from './data-entry/entry-update.js'\n/* Reading an application's lists - an app registers what it lets read; a mode names it (design/ai/read-targets.md). */\nexport * from './data-read/read-target.js'\nexport { registerReadTarget, readCategoryOf, registerDetailRead, detailCategoryOf, runDetail, type DetailRun } from './data-read/read-tools.js'\nexport * from './data-read/list-read.js'\nexport * from './people/index.js'\n/* The AI 작업 패널 - large results on a page of their own (design/ai/workspace.md). */\nexport * from './workspace/workspace-blocks.js'\n/* 무엇이 근거인가 — 도구 결과 밖의 셋(프롬프트 · 대화 · 화면 스냅숏). */\nexport * from './grounding-sources.js'\n/* 앵커 순수 로직 — 호스트가 앵커 종류를 참조한다(리졸버는 데코레이터 때문에 무겁다). */\nexport * from './chat-session/session-anchor.js'\n/* Who may read a conversation — one rule, also asked by doors outside this package (board-ai's revertPatch). */\nexport * from './chat-session/session-visibility.js'\nexport * from './chat-session/index.js'\n/* 순수 로직들 — 호스트(board-ai 등)가 같은 규칙을 쓰라고 공개한다. 베끼면 한쪽만 고쳐진다. */\nexport * from './chat-session/session-inbox.js'\nexport * from './chat-session/attachment-policy.js'\nexport * from './chat-session/session-purge.js'\nexport * from './chat-session/session-activity-publish.js'\nexport * from './chat-session/session-activity-broadcast.js'\nexport * from './chat-message/llm-history.js'\nexport * from './chat-message/history-summary.js'\nexport * from './chat-message/fold-history.js'\n/* 상한 밖으로 밀려난 앞부분을 요약으로 접는 orchestration — 중립 문이 부른다. */\nexport * from './chat-message/fold-session-history.js'\nexport * from './chat-message/chat-message-publish.js'\nexport * from './chat-message/chat-message-broadcast.js'\nexport * from './chat-session-participant/invite-notification.js'\n/* 멘션이 사람을 불러들이는 자리 — 사람의 말을 저장하는 문만 부른다(ADR-0071 결정 1). */\nexport * from './chat-session-participant/mention-invite.js'\nexport * from './chat-session-participant/presence.js'\nexport * from './chat-message/index.js'\nexport * from './chat-session-participant/index.js'\n/* Reading the stored proposals of a conversation and whether one is answered - a package that applies its own card reads them as entry does. */\nexport { PROPOSAL_OUTCOME_PREFIX } from './chat-message/proposal-outcome.js'\nexport { assertMayWriteSession } from './chat-session/session-write-gate.js'\n/* A mode run with no person in it - a scheduled draft (operato-application/design/ai/unattended-run.md). */\nexport * from './unattended-run/index.js'\n\nexport const entities = [...ChatSessionEntities, ...ChatMessageEntities, ...ChatSessionParticipantEntities, ...UnattendedRunEntities]\n\nexport const schema = {\n resolverClasses: [\n ChatSessionResolver,\n /* 문서를 갖지 않은 표면의 대화 — board 를 안 싣는 제품이 물어볼 수 있는 자리. */\n AssistantChatResolver,\n /* 화면이 자기 대화가 무엇을 주는지 묻는 자리 — 문구는 서버가 요청 로케일로 옮겨 낸다. */\n AssistantModeResolver,\n /* 「이 배포에 AI 가 있나 · 무엇이 선언 없이 등록됐나」 — 창구 하나(표준 A7-a). */\n AssistantCapabilityResolver,\n /* A domain's AI agents - the settings card and the dock's picker (design/ai/agent-settings.md). */\n AiAgentResolver,\n ChatMessageSubscription,\n /* 「입력 중」 — 저장하지 않는 방의 한 줄. 듣는 사람은 메시지와 같은 방 판정을 지난다. */\n ChatTypingSubscription,\n /* 내가 참여한 모든 세션의 활동 — 창을 닫아 둔 표면이 배지·목록을 갱신할 수 있게. */\n MySessionActivitySubscription,\n /* 사람이 누른 입력 제안을 쓰는 자리 — 행마다 앱의 코드로, 그 사람의 권한으로. */\n EntryProposalResolver\n ]\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yEAAgE;AAChE,6EAAoE;AACpE,4FAAmF;AACnF,yFAAgF;AAChF,iEAAwD;AACxD,sGAA+F;AAC/F,8FAAqF;AACrF,4FAAmF;AACnF,sDAAyE;AACzE,sDAAyE;AACzE,kEAAgG;AAChG,8CAA2C;AAC3C,2CAAwC;AACxC,8CAA2C;AAC3C,sEAAsE;AACtE,0CAAuC;AACvC,0CAAuC;AACvC,iHAAiH;AACjH,6BAA0B;AAC1B,wDAA6E;AAE7E,qDAA0B;AAC1B,qEAA0C;AAC1C,uEAA4C;AAC5C,oGAAoG;AACpG,oEAAyC;AACzC,iEAA2D;AAAlD,0HAAA,iBAAiB,OAAA;AAC1B,6EAAkD;AAClD;;;GAGG;AACH,2DAAgC;AAChC,+GAA+G;AAC/G,uEAA4C;AAC5C,8DAA+F;AAAtF,qHAAA,mBAAmB,OAAA;AAAE,iHAAA,eAAe,OAAA;AAAE,6GAAA,WAAW,OAAA;AAC1D,yHAAyH;AACzH,gEAA0E;AAAjE,iHAAA,cAAc,OAAA;AAAE,8GAAA,WAAW,OAAA;AACpC,uHAAuH;AACvH,qEAA0C;AAC1C,2DAA+I;AAAtI,mHAAA,kBAAkB,OAAA;AAAE,+GAAA,cAAc,OAAA;AAAE,mHAAA,kBAAkB,OAAA;AAAE,iHAAA,gBAAgB,OAAA;AAAE,0GAAA,SAAS,OAAA;AAC5F,mEAAwC;AACxC,4DAAiC;AACjC,mFAAmF;AACnF,0EAA+C;AAC/C,gDAAgD;AAChD,iEAAsC;AACtC,sDAAsD;AACtD,2EAAgD;AAChD,gHAAgH;AAChH,+EAAoD;AACpD,kEAAuC;AACvC,8DAA8D;AAC9D,0EAA+C;AAC/C,8EAAmD;AACnD,0EAA+C;AAC/C,qFAA0D;AAC1D,uFAA4D;AAC5D,wEAA6C;AAC7C,4EAAiD;AACjD,yEAA8C;AAC9C,wDAAwD;AACxD,iFAAsD;AACtD,iFAAsD;AACtD,mFAAwD;AACxD,4FAAiE;AACjE,2DAA2D;AAC3D,uFAA4D;AAC5D,iFAAsD;AACtD,kEAAuC;AACvC,8EAAmD;AACnD,gJAAgJ;AAChJ,0EAA4E;AAAnE,8HAAA,uBAAuB,OAAA;AAChC,8EAA4E;AAAnE,8HAAA,qBAAqB,OAAA;AAC9B,4GAA4G;AAC5G,oEAAyC;AAE5B,QAAA,QAAQ,GAAG,CAAC,GAAG,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,GAAG,mBAA8B,EAAE,GAAG,mBAAqB,CAAC,CAAA;AAExH,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,8CAAmB;QACnB,sDAAsD;QACtD,kDAAqB;QACrB,uDAAuD;QACvD,kDAAqB;QACrB,wDAAwD;QACxD,8DAA2B;QAC3B,mGAAmG;QACnG,sCAAe;QACf,sDAAuB;QACvB,wDAAwD;QACxD,oDAAsB;QACtB,qDAAqD;QACrD,gEAA6B;QAC7B,mDAAmD;QACnD,yCAAqB;KACtB;CACF,CAAA","sourcesContent":["import { ChatSessionResolver } from './chat-session-resolver.js'\nimport { AssistantChatResolver } from './assistant-chat-resolver.js'\nimport { AssistantModeResolver } from './assistant-mode/assistant-mode-resolver.js'\nimport { AssistantCapabilityResolver } from './assistant-capability-resolver.js'\nimport { AiAgentResolver } from './ai-agent-resolver.js'\nimport { MySessionActivitySubscription } from './chat-session/session-activity-subscription.js'\nimport { ChatMessageSubscription } from './chat-message/chat-message-subscription.js'\nimport { ChatTypingSubscription } from './chat-message/chat-typing-subscription.js'\nimport { entities as ChatSessionEntities } from './chat-session/index.js'\nimport { entities as ChatMessageEntities } from './chat-message/index.js'\nimport { entities as ChatSessionParticipantEntities } from './chat-session-participant/index.js'\nimport './chat-session/attachment-tools.js'\nimport './chat-session/session-purge.js'\nimport './chat-session/attachment-route.js'\nimport { EntryProposalResolver } from './data-entry/entry-resolver.js'\nimport './workspace/workspace-tools.js'\nimport './help-documents/help-tools.js'\n/* Who works here, and the card that brings one of them into a conversation - every conversation carries both. */\nimport './people/index.js'\nimport { entities as UnattendedRunEntities } from './unattended-run/index.js'\n\nexport * from './types.js'\nexport * from './chat-session-resolver.js'\nexport * from './assistant-chat-resolver.js'\n/* The mode registry — each app server declares what its conversations are (ADR-0061 decision 7). */\nexport * from './assistant-mode/index.js'\nexport { requestTranslator } from './request-translator.js'\nexport * from './assistant-capability-resolver.js'\n/*\n * 대화 각본 하네스는 **런타임 export 에서 뺀다**(ADR-0070 A15 결정 ④) — 시험 도구가 서버 번들에\n * 실린다. 시험은 경로로 가져온다: `…/service/testing/conversation-script.js`.\n */\nexport * from './tool-access.js'\n/* Data entry from material - an app registers what it can enter; a mode names it (design/ai/data-entry.md). */\nexport * from './data-entry/entry-target.js'\nexport { registerEntryTarget, entryCategoryOf, runAsCaller } from './data-entry/entry-tools.js'\n/* An application's tool that prepares many changes at once makes the same change card the model's would (2026-10-24). */\nexport { proposeChanges, MAX_CHANGES } from './data-entry/entry-update.js'\n/* Reading an application's lists - an app registers what it lets read; a mode names it (design/ai/read-targets.md). */\nexport * from './data-read/read-target.js'\nexport { registerReadTarget, readCategoryOf, registerDetailRead, detailCategoryOf, runDetail, type DetailRun } from './data-read/read-tools.js'\nexport * from './data-read/list-read.js'\nexport * from './people/index.js'\n/* The AI 작업 패널 - large results on a page of their own (design/ai/workspace.md). */\nexport * from './workspace/workspace-blocks.js'\n/* 무엇이 근거인가 — 도구 결과 밖의 셋(프롬프트 · 대화 · 화면 스냅숏). */\nexport * from './grounding-sources.js'\n/* 앵커 순수 로직 — 호스트가 앵커 종류를 참조한다(리졸버는 데코레이터 때문에 무겁다). */\nexport * from './chat-session/session-anchor.js'\n/* Who may read a conversation — one rule, also asked by doors outside this package (board-ai's revertPatch). */\nexport * from './chat-session/session-visibility.js'\nexport * from './chat-session/index.js'\n/* 순수 로직들 — 호스트(board-ai 등)가 같은 규칙을 쓰라고 공개한다. 베끼면 한쪽만 고쳐진다. */\nexport * from './chat-session/session-inbox.js'\nexport * from './chat-session/attachment-policy.js'\nexport * from './chat-session/session-purge.js'\nexport * from './chat-session/session-activity-publish.js'\nexport * from './chat-session/session-activity-broadcast.js'\nexport * from './chat-message/llm-history.js'\nexport * from './chat-message/history-summary.js'\nexport * from './chat-message/fold-history.js'\n/* 상한 밖으로 밀려난 앞부분을 요약으로 접는 orchestration — 중립 문이 부른다. */\nexport * from './chat-message/fold-session-history.js'\nexport * from './chat-message/chat-message-publish.js'\nexport * from './chat-message/chat-message-broadcast.js'\nexport * from './chat-session-participant/invite-notification.js'\n/* 멘션이 사람을 불러들이는 자리 — 사람의 말을 저장하는 문만 부른다(ADR-0071 결정 1). */\nexport * from './chat-session-participant/mention-invite.js'\nexport * from './chat-session-participant/presence.js'\nexport * from './chat-message/index.js'\nexport * from './chat-session-participant/index.js'\n/* Reading the stored proposals of a conversation and whether one is answered - a package that applies its own card reads them as entry does. */\nexport { PROPOSAL_OUTCOME_PREFIX } from './chat-message/proposal-outcome.js'\nexport { assertMayWriteSession } from './chat-session/session-write-gate.js'\n/* A mode run with no person in it - a scheduled draft (operato-application/design/ai/unattended-run.md). */\nexport * from './unattended-run/index.js'\n\nexport const entities = [...ChatSessionEntities, ...ChatMessageEntities, ...ChatSessionParticipantEntities, ...UnattendedRunEntities]\n\nexport const schema = {\n resolverClasses: [\n ChatSessionResolver,\n /* 문서를 갖지 않은 표면의 대화 — board 를 안 싣는 제품이 물어볼 수 있는 자리. */\n AssistantChatResolver,\n /* 화면이 자기 대화가 무엇을 주는지 묻는 자리 — 문구는 서버가 요청 로케일로 옮겨 낸다. */\n AssistantModeResolver,\n /* 「이 배포에 AI 가 있나 · 무엇이 선언 없이 등록됐나」 — 창구 하나(표준 A7-a). */\n AssistantCapabilityResolver,\n /* A domain's AI agents - the settings card and the dock's picker (design/ai/agent-settings.md). */\n AiAgentResolver,\n ChatMessageSubscription,\n /* 「입력 중」 — 저장하지 않는 방의 한 줄. 듣는 사람은 메시지와 같은 방 판정을 지난다. */\n ChatTypingSubscription,\n /* 내가 참여한 모든 세션의 활동 — 창을 닫아 둔 표면이 배지·목록을 갱신할 수 있게. */\n MySessionActivitySubscription,\n /* 사람이 누른 입력 제안을 쓰는 자리 — 행마다 앱의 코드로, 그 사람의 권한으로. */\n EntryProposalResolver\n ]\n}\n"]}