@things-factory/board-ai 10.1.52 → 10.1.53
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-client/server/service/assistant.d.ts +6 -0
- package/dist-client/server/service/assistant.js +12 -1
- package/dist-client/server/service/assistant.js.map +1 -1
- package/dist-client/server/service/types.d.ts +6 -0
- package/dist-client/server/service/types.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/assistant.d.ts +6 -0
- package/dist-server/service/assistant.js +13 -2
- package/dist-server/service/assistant.js.map +1 -1
- package/dist-server/service/board-ai-resolver.js +5 -1
- package/dist-server/service/board-ai-resolver.js.map +1 -1
- package/dist-server/service/types.d.ts +6 -0
- package/dist-server/service/types.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/service/assistant.ts +14 -1
- package/server/service/board-ai-resolver.ts +6 -1
- package/server/service/dock-contract.test.ts +26 -1
- package/server/service/types.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/board-ai",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.53",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"@operato/i18n": "^10.0.0",
|
|
33
33
|
"@operato/scene-ops": "^10.14.1",
|
|
34
34
|
"@operato/styles": "^10.0.0",
|
|
35
|
-
"@things-factory/ai-assistant": "^10.1.
|
|
36
|
-
"@things-factory/ai-client-base": "^10.1.
|
|
35
|
+
"@things-factory/ai-assistant": "^10.1.53",
|
|
36
|
+
"@things-factory/ai-client-base": "^10.1.53",
|
|
37
37
|
"@things-factory/auth-base": "^10.1.47",
|
|
38
|
-
"@things-factory/board-import": "^10.1.
|
|
38
|
+
"@things-factory/board-import": "^10.1.53",
|
|
39
39
|
"@things-factory/env": "^10.1.20",
|
|
40
40
|
"@things-factory/shell": "^10.1.47",
|
|
41
41
|
"dompurify": "^3.0.0",
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"copyfiles": "^2.4.1",
|
|
48
48
|
"rimraf": "^5.0.0"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "1bdb0c604614735fd5a5467aee1e56f53be6b89e"
|
|
51
51
|
}
|
|
@@ -118,6 +118,18 @@ export interface BoardAIAssistantOptions {
|
|
|
118
118
|
categories?: ComponentCategory[]
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Said to the model when the person's rights turned the editing tools off (`boardToolsWithheld`). The editing
|
|
123
|
+
* guide above still describes the tools, so without this the model calls them anyway, fails on each, and
|
|
124
|
+
* writes the calls out as its answer.
|
|
125
|
+
*/
|
|
126
|
+
export const BOARD_EDIT_WITHHELD =
|
|
127
|
+
'==== BOARD EDITING IS OFF FOR THIS PERSON ====\n' +
|
|
128
|
+
'This person has no permission to change boards (board-ai mutation), so this conversation has no editing tool - ' +
|
|
129
|
+
'the editing instructions above do not apply. Never call an editing tool and never write a tool call out as text. ' +
|
|
130
|
+
'When asked to change the board, say it cannot be changed from this conversation because changing boards needs the ' +
|
|
131
|
+
'board edit permission, which an administrator can grant. You can still answer questions about the board.'
|
|
132
|
+
|
|
121
133
|
export class DefaultBoardAIAssistant implements BoardAIAssistant {
|
|
122
134
|
readonly id: string
|
|
123
135
|
constructor(private base: AIClient, private options: BoardAIAssistantOptions = {}) {
|
|
@@ -183,7 +195,8 @@ export class DefaultBoardAIAssistant implements BoardAIAssistant {
|
|
|
183
195
|
const systemPrompt =
|
|
184
196
|
this.buildSystemPromptForTools(knownTypes, categories, schemas) +
|
|
185
197
|
(surface ? `\n\n==== THIS SURFACE (declared by the app) ====\n${surface}` : '') +
|
|
186
|
-
(guidance.length ? `\n\n==== TOOL USE RULES (from the tools exposed to this conversation) ====\n${guidance.join('\n')}` : '')
|
|
198
|
+
(guidance.length ? `\n\n==== TOOL USE RULES (from the tools exposed to this conversation) ====\n${guidance.join('\n')}` : '') +
|
|
199
|
+
(!gate.coreOn && options.boardToolsWithheld ? `\n\n${BOARD_EDIT_WITHHELD}` : '')
|
|
187
200
|
|
|
188
201
|
const selectedRefids = (options.selectedRefids ?? []).filter(
|
|
189
202
|
(n): n is number => typeof n === 'number' && Number.isFinite(n)
|
|
@@ -439,13 +439,18 @@ export class BoardAIChatResolver {
|
|
|
439
439
|
}))
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
/* The surface wanted board editing and the person's rights took it away - the model is told, so it says so. */
|
|
443
|
+
const boardTools = await effectiveBoardTools(input.boardTools, context)
|
|
444
|
+
const boardToolsWithheld = input.boardTools !== false && boardTools === false
|
|
445
|
+
|
|
442
446
|
const r = await assistant.chat(llmMessages, input.currentBoard ?? undefined, {
|
|
443
447
|
scopes: input.scopes,
|
|
444
448
|
hostContext: input.hostContext ?? undefined,
|
|
445
449
|
surfacePrompt: modeSettings?.systemPrompt,
|
|
446
450
|
/* 대화면별 도구 노출 — 모드가 있으면 서버 선언(빈 목록 = 외부 도구 없음), 없으면 호출자 값(미지정 = 전부). */
|
|
447
451
|
toolCategories: modeSettings ? modeSettings.toolCategories ?? [] : input.toolCategories ?? undefined,
|
|
448
|
-
boardTools
|
|
452
|
+
boardTools,
|
|
453
|
+
boardToolsWithheld,
|
|
449
454
|
requireGroundingTools: modeSettings ? modeSettings.requireToolOnFirstTurn : input.requireGroundingTools ?? undefined,
|
|
450
455
|
knownTypes: input.knownTypes,
|
|
451
456
|
categories: input.categories as ComponentCategory[] | undefined,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import type { AIClient } from '@things-factory/ai-client-base'
|
|
17
17
|
import { registerToolCategory, clearToolRegistry } from '@things-factory/ai-client-base'
|
|
18
18
|
|
|
19
|
-
import { DefaultBoardAIAssistant } from './assistant'
|
|
19
|
+
import { BOARD_EDIT_WITHHELD, DefaultBoardAIAssistant } from './assistant'
|
|
20
20
|
|
|
21
21
|
/** 스크립트된 턴을 돌려주는 가짜 provider — 호출 옵션도 기록한다(toolChoice 확인용). */
|
|
22
22
|
function mockClient(turns: Array<{ text?: string; toolCalls: any[] }>) {
|
|
@@ -306,3 +306,28 @@ describe('도크 계약 — 도구 사용 규율이 프롬프트에 실린다',
|
|
|
306
306
|
expect(calls[0].options.systemPrompt).not.toContain('OTHER-RULE')
|
|
307
307
|
})
|
|
308
308
|
})
|
|
309
|
+
|
|
310
|
+
describe('dock contract - board editing withheld by rights', () => {
|
|
311
|
+
it('the model is told editing is off when the rights took the tools away', async () => {
|
|
312
|
+
const { client, calls } = mockClient([{ text: 'I cannot change the board here.', toolCalls: [] }])
|
|
313
|
+
await new DefaultBoardAIAssistant(client).chat([{ role: 'user', content: 'add a title' }], { components: [] } as any, {
|
|
314
|
+
boardTools: false,
|
|
315
|
+
boardToolsWithheld: true
|
|
316
|
+
})
|
|
317
|
+
expect(calls[0].options.systemPrompt).toContain(BOARD_EDIT_WITHHELD)
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it('a surface that turned the tools off itself is not told about rights', async () => {
|
|
321
|
+
const { client, calls } = mockClient([{ text: 'ok', toolCalls: [] }])
|
|
322
|
+
await new DefaultBoardAIAssistant(client).chat([{ role: 'user', content: 'status?' }], undefined, { boardTools: false })
|
|
323
|
+
expect(calls[0].options.systemPrompt).not.toContain(BOARD_EDIT_WITHHELD)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
it('with the tools on, nothing is said', async () => {
|
|
327
|
+
const { client, calls } = mockClient([{ text: 'ok', toolCalls: [] }])
|
|
328
|
+
await new DefaultBoardAIAssistant(client).chat([{ role: 'user', content: 'add a title' }], { components: [] } as any, {
|
|
329
|
+
boardToolsWithheld: true
|
|
330
|
+
})
|
|
331
|
+
expect(calls[0].options.systemPrompt).not.toContain(BOARD_EDIT_WITHHELD)
|
|
332
|
+
})
|
|
333
|
+
})
|
package/server/service/types.ts
CHANGED
|
@@ -37,6 +37,12 @@ export interface ChatOptions {
|
|
|
37
37
|
* 되돌릴 수 있는 편집이 한 대화에 섞이지 않게 한다.
|
|
38
38
|
*/
|
|
39
39
|
boardTools?: boolean
|
|
40
|
+
/**
|
|
41
|
+
* The surface asked for board editing but the person has no board-ai:mutation, so the editing tools are off.
|
|
42
|
+
* The model is told in so many words - otherwise the editing guide in the prompt leads it to call tools that
|
|
43
|
+
* are not there and to write the calls out as text.
|
|
44
|
+
*/
|
|
45
|
+
boardToolsWithheld?: boolean
|
|
40
46
|
/**
|
|
41
47
|
* **첫 턴에 도구 호출을 강제**한다. 라이브 상태를 다루는 대화면(운영 협의)에서 켠다.
|
|
42
48
|
*
|