@things-factory/board-ai 10.0.1 → 10.0.3
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/client/components/board-ai-chat.ts +565 -21
- package/client/components/chat-echo-dedup.test.ts +59 -3
- package/client/components/chat-echo-dedup.ts +32 -0
- package/client/components/chat-input-builder.ts +6 -0
- package/dist-client/client/components/board-ai-chat.d.ts +80 -0
- package/dist-client/client/components/board-ai-chat.js +540 -18
- package/dist-client/client/components/board-ai-chat.js.map +1 -1
- package/dist-client/client/components/chat-echo-dedup.d.ts +2 -0
- package/dist-client/client/components/chat-echo-dedup.js +29 -0
- package/dist-client/client/components/chat-echo-dedup.js.map +1 -1
- package/dist-client/client/components/chat-echo-dedup.test.js +53 -3
- package/dist-client/client/components/chat-echo-dedup.test.js.map +1 -1
- package/dist-client/client/components/chat-input-builder.d.ts +5 -0
- package/dist-client/client/components/chat-input-builder.js +1 -0
- package/dist-client/client/components/chat-input-builder.js.map +1 -1
- package/dist-client/server/service/agentic-loop.d.ts +33 -0
- package/dist-client/server/service/agentic-loop.js +80 -10
- package/dist-client/server/service/agentic-loop.js.map +1 -1
- package/dist-client/server/service/assistant.js +32 -5
- package/dist-client/server/service/assistant.js.map +1 -1
- package/dist-client/server/service/grounding.d.ts +17 -0
- package/dist-client/server/service/grounding.js +42 -0
- package/dist-client/server/service/grounding.js.map +1 -0
- package/dist-client/server/service/types.d.ts +39 -0
- package/dist-client/server/service/types.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/agentic-loop.d.ts +33 -0
- package/dist-server/service/agentic-loop.js +81 -10
- package/dist-server/service/agentic-loop.js.map +1 -1
- package/dist-server/service/assistant.js +31 -4
- package/dist-server/service/assistant.js.map +1 -1
- package/dist-server/service/board-ai-resolver.d.ts +15 -0
- package/dist-server/service/board-ai-resolver.js +121 -2
- package/dist-server/service/board-ai-resolver.js.map +1 -1
- package/dist-server/service/chat-message/chat-message.d.ts +12 -0
- package/dist-server/service/chat-message/chat-message.js +23 -0
- package/dist-server/service/chat-message/chat-message.js.map +1 -1
- package/dist-server/service/chat-message/fold-history.d.ts +30 -0
- package/dist-server/service/chat-message/fold-history.js +29 -0
- package/dist-server/service/chat-message/fold-history.js.map +1 -0
- package/dist-server/service/chat-message/history-summary.d.ts +43 -0
- package/dist-server/service/chat-message/history-summary.js +77 -0
- package/dist-server/service/chat-message/history-summary.js.map +1 -0
- package/dist-server/service/chat-message/llm-history.d.ts +19 -0
- package/dist-server/service/chat-message/llm-history.js +31 -1
- package/dist-server/service/chat-message/llm-history.js.map +1 -1
- package/dist-server/service/chat-session/chat-session.d.ts +8 -0
- package/dist-server/service/chat-session/chat-session.js +5 -0
- package/dist-server/service/chat-session/chat-session.js.map +1 -1
- package/dist-server/service/chat-session/session-inbox.d.ts +26 -0
- package/dist-server/service/chat-session/session-inbox.js +41 -0
- package/dist-server/service/chat-session/session-inbox.js.map +1 -1
- package/dist-server/service/chat-session-participant/chat-session-participant.d.ts +11 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.js +17 -1
- package/dist-server/service/chat-session-participant/chat-session-participant.js.map +1 -1
- package/dist-server/service/chat-session-resolver.d.ts +44 -1
- package/dist-server/service/chat-session-resolver.js +306 -6
- package/dist-server/service/chat-session-resolver.js.map +1 -1
- package/dist-server/service/grounding.d.ts +17 -0
- package/dist-server/service/grounding.js +46 -0
- package/dist-server/service/grounding.js.map +1 -0
- package/dist-server/service/types.d.ts +39 -0
- package/dist-server/service/types.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/server/service/agentic-loop.test.ts +154 -0
- package/server/service/agentic-loop.ts +108 -10
- package/server/service/assistant.ts +36 -5
- package/server/service/board-ai-resolver.ts +131 -2
- package/server/service/chat-message/chat-message.ts +26 -0
- package/server/service/chat-message/fold-history.test.ts +98 -0
- package/server/service/chat-message/fold-history.ts +60 -0
- package/server/service/chat-message/history-summary.test.ts +127 -0
- package/server/service/chat-message/history-summary.ts +100 -0
- package/server/service/chat-message/llm-history.test.ts +65 -0
- package/server/service/chat-message/llm-history.ts +48 -1
- package/server/service/chat-session/chat-session.ts +11 -0
- package/server/service/chat-session/session-inbox.test.ts +69 -1
- package/server/service/chat-session/session-inbox.ts +45 -0
- package/server/service/chat-session-participant/chat-session-participant.ts +14 -0
- package/server/service/chat-session-resolver.ts +297 -5
- package/server/service/dock-contract.test.ts +305 -0
- package/server/service/grounding.test.ts +55 -0
- package/server/service/grounding.ts +53 -0
- package/server/service/types.ts +39 -0
- package/translations/en.json +16 -1
- package/translations/ja.json +16 -1
- package/translations/ko.json +15 -0
- package/translations/ms.json +16 -1
- package/translations/zh.json +16 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 근거집합의 정의 검증 — 무엇을 "모델이 받은 것" 으로 볼 것인가.
|
|
3
|
+
*
|
|
4
|
+
* 판정 규칙(식별자 대조·소음 제거)은 ai-client-base 가 소유하고 그쪽에서 검증한다.
|
|
5
|
+
* 여기서 지키는 것은 **하나도 빠뜨리지 않는 것**이다 — 근거를 빠뜨리면 정상 답에 경고가 붙고,
|
|
6
|
+
* 그 오탐이 반복되면 사용자는 경고를 무시한다(가드가 죽는다).
|
|
7
|
+
*/
|
|
8
|
+
import { buildGroundedCorpus, checkReplyGrounding } from './grounding'
|
|
9
|
+
|
|
10
|
+
describe('buildGroundedCorpus', () => {
|
|
11
|
+
it('네 갈래를 모두 담는다 — 프롬프트·보드 문맥·이력·도구 결과', () => {
|
|
12
|
+
const corpus = buildGroundedCorpus({
|
|
13
|
+
systemPrompt: 'types: dock-door',
|
|
14
|
+
boardContext: '{"components":[{"id":"gauge-1"}]}',
|
|
15
|
+
messages: ['aisle-2 상태 알려줘'],
|
|
16
|
+
toolResults: ['{"nodes":[{"id":"rack-9"}]}']
|
|
17
|
+
})
|
|
18
|
+
for (const id of ['dock-door', 'gauge-1', 'aisle-2', 'rack-9']) {
|
|
19
|
+
expect(corpus).toContain(id)
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('빈 갈래는 건너뛴다 — 근거 없는 대화(즉석 질문)도 성립한다', () => {
|
|
24
|
+
expect(buildGroundedCorpus({})).toBe('')
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe('checkReplyGrounding', () => {
|
|
29
|
+
const sources = {
|
|
30
|
+
systemPrompt: 'creatable types: dock-door, twin-node',
|
|
31
|
+
boardContext: '{"components":[{"id":"dock-1","name":"입고 도크"}]}',
|
|
32
|
+
messages: ['지금 상태 어때?'],
|
|
33
|
+
toolResults: ['{"instances":[{"instanceId":"hatiolab-wms"}],"nodes":[{"id":"dock-1"}]}']
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
it('도구가 돌려준 대상으로 답하면 경고가 없다', () => {
|
|
37
|
+
expect(checkReplyGrounding('hatiolab-wms 의 dock-1 은 여유롭습니다.', sources)).toEqual([])
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('프롬프트의 타입 이름을 말하는 것은 근거 있는 것이다 — 오탐 방지', () => {
|
|
41
|
+
expect(checkReplyGrounding('dock-door 컴포넌트를 추가했습니다.', sources)).toEqual([])
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('근거 밖의 대상을 지목하면 경고한다', () => {
|
|
45
|
+
expect(checkReplyGrounding('dock-5 에 적체가 있습니다.', sources)).toEqual(['dock-5'])
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('도구를 부르지 않았으면 도구 결과가 근거에 없다 — 그때 언급한 대상은 경고 대상', () => {
|
|
49
|
+
expect(checkReplyGrounding('rack-3 이 포화입니다.', { ...sources, toolResults: [] })).toEqual(['rack-3'])
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('빈 답은 검사하지 않는다', () => {
|
|
53
|
+
expect(checkReplyGrounding('', sources)).toEqual([])
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 접지 검사 — 이 대화면의 답이 **모델이 실제로 받은 것** 안에서 말했는지.
|
|
3
|
+
*
|
|
4
|
+
* ── 왜 board-ai 에 필요한가 ─────────────────────────────────────────────────
|
|
5
|
+
* 협의 도크(operato-twin)는 board-ai 위에 서 있고, 여기서 사람들이 운영 상태를 묻는다.
|
|
6
|
+
* 헤더 경로(twin-ai)에는 접지 가드가 있었지만 도크 경로에는 없었다 — 같은 질문에 대해
|
|
7
|
+
* 한쪽은 검증되고 한쪽은 검증되지 않는 상태였다. 판정 규칙은 공용 모듈이 소유하고
|
|
8
|
+
* (`@things-factory/ai-client-base` 의 grounding), 이 파일은 **무엇을 근거로 볼 것인가**만 정한다.
|
|
9
|
+
*
|
|
10
|
+
* ── 근거집합의 정의 ─────────────────────────────────────────────────────────
|
|
11
|
+
* 모델이 이 턴에 받은 전부다. 하나라도 빼면 정상 답이 경고를 받는다(오탐):
|
|
12
|
+
* · systemPrompt — 생성 가능한 컴포넌트 타입 목록 등. 여기 있는 이름을 말하는 건 정상이다.
|
|
13
|
+
* · boardContext — 현재 보드 요약(컴포넌트 id·이름). 보드를 두고 말하는 근거.
|
|
14
|
+
* · messages — 사용자·이력 텍스트. 사용자가 말한 식별자를 되받는 건 정상이다.
|
|
15
|
+
* · toolResults — 도구가 돌려준 원문(압축 전). 운영 상태 답의 유일한 사실 근거.
|
|
16
|
+
*
|
|
17
|
+
* ── 사정거리 ────────────────────────────────────────────────────────────────
|
|
18
|
+
* 식별자만 본다. "지게차들이 바쁘게 움직인다" 처럼 **식별자 없이 지어낸 서술**은 잡지 못한다 —
|
|
19
|
+
* 그건 도구를 부르지 않고 답한 경우이고, 도구 호출을 강제하는 별도 레버의 몫이다.
|
|
20
|
+
*/
|
|
21
|
+
import { groundingWarnings } from '@things-factory/ai-client-base'
|
|
22
|
+
|
|
23
|
+
export interface GroundingSources {
|
|
24
|
+
/** 시스템 프롬프트(타입 목록·규칙). */
|
|
25
|
+
systemPrompt?: string
|
|
26
|
+
/** 보드 상태 요약 등 대화 앞에 붙인 문맥. */
|
|
27
|
+
boardContext?: string
|
|
28
|
+
/** 사용자·어시스턴트 이력 텍스트. */
|
|
29
|
+
messages?: string[]
|
|
30
|
+
/** tool_result 로 회신된 원문(시간순). */
|
|
31
|
+
toolResults?: string[]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 근거집합을 한 덩어리 문자열로. (id 토큰 대조만 하므로 구분자는 개행으로 충분하다.) */
|
|
35
|
+
export function buildGroundedCorpus(sources: GroundingSources): string {
|
|
36
|
+
return [
|
|
37
|
+
sources.systemPrompt ?? '',
|
|
38
|
+
sources.boardContext ?? '',
|
|
39
|
+
...(sources.messages ?? []),
|
|
40
|
+
...(sources.toolResults ?? [])
|
|
41
|
+
]
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.join('\n')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 답이 근거 밖의 식별자를 지목했으면 그 목록. 비면 접지 정상.
|
|
48
|
+
* 답을 고치거나 막지 않는다 — 사용자에게 표시할 경고만 낸다.
|
|
49
|
+
*/
|
|
50
|
+
export function checkReplyGrounding(reply: string, sources: GroundingSources): string[] {
|
|
51
|
+
if (!reply) return []
|
|
52
|
+
return groundingWarnings(reply, buildGroundedCorpus(sources))
|
|
53
|
+
}
|
package/server/service/types.ts
CHANGED
|
@@ -27,6 +27,15 @@ export interface ChatOptions {
|
|
|
27
27
|
* 되돌릴 수 있는 편집이 한 대화에 섞이지 않게 한다.
|
|
28
28
|
*/
|
|
29
29
|
boardTools?: boolean
|
|
30
|
+
/**
|
|
31
|
+
* **첫 턴에 도구 호출을 강제**한다. 라이브 상태를 다루는 대화면(운영 협의)에서 켠다.
|
|
32
|
+
*
|
|
33
|
+
* 접지 가드는 답이 지어낸 **식별자**를 잡지만, 식별자 없이 지어낸 **상황 서술**은 잡지 못한다
|
|
34
|
+
* ("지게차들이 바쁘게 움직이고 있다" — 실제로 나온 답이다). 그건 도구를 아예 부르지 않고 답한
|
|
35
|
+
* 경우여서 사후 검사로 막을 수 없다. 첫 턴에 무엇이든 조회하게 만들면 근거 없이 상태를 단언할
|
|
36
|
+
* 길이 없어진다. 켜고 끄는 판단은 대화면이 한다 — 서버가 질문 내용을 눈치로 분류하지 않는다.
|
|
37
|
+
*/
|
|
38
|
+
requireGroundingTools?: boolean
|
|
30
39
|
/**
|
|
31
40
|
* 호스트(대화면)가 실어 보내는 **문맥** — 도구가 ctx.state.host 로 읽는다.
|
|
32
41
|
*
|
|
@@ -117,6 +126,22 @@ export interface ToolUsage {
|
|
|
117
126
|
result: any
|
|
118
127
|
/** read tool / write tool 분류 */
|
|
119
128
|
kind: 'read' | 'write' | 'unknown'
|
|
129
|
+
/**
|
|
130
|
+
* 몇 번째 LLM 턴에서 불렀는가(0부터). 판단 과정을 단계로 읽을 수 있게 한다 —
|
|
131
|
+
* "조회 → 거절 → 정정 → 제안" 이 한 턴 안의 일인지 여러 턴에 걸친 일인지가 진단의 절반이다.
|
|
132
|
+
*/
|
|
133
|
+
iter?: number
|
|
134
|
+
/**
|
|
135
|
+
* 이 호출이 **어떻게 끝났는가** — 화면이 배지로 보여줄 판정.
|
|
136
|
+
* ok 조회·실행이 정상 완료
|
|
137
|
+
* rejected 도구가 거절(인자 누락·대상 없음 등). 무엇이 빠졌는지는 result 에 있다.
|
|
138
|
+
* queued 보드 편집처럼 클라이언트에서 적용될 예정
|
|
139
|
+
* proposed 조치 제안이 만들어졌다(실행 아님 — 사용자가 버튼을 누른다)
|
|
140
|
+
* folded 같은 효과의 제안이 이미 있어 접혔다. **조용히 버리지 않는다** — 접힌 사실이 보여야
|
|
141
|
+
* "왜 카드가 하나뿐인가" 를 추적할 수 있다.
|
|
142
|
+
* error 알 수 없는 도구·검증 실패
|
|
143
|
+
*/
|
|
144
|
+
outcome?: 'ok' | 'rejected' | 'queued' | 'proposed' | 'folded' | 'error'
|
|
120
145
|
}
|
|
121
146
|
|
|
122
147
|
export interface ChatResponse {
|
|
@@ -133,6 +158,20 @@ export interface ChatResponse {
|
|
|
133
158
|
followUp?: string
|
|
134
159
|
/** AI 가 응답 만드는 과정에서 호출한 도구들 (시간순). UI fold-able 박스용. */
|
|
135
160
|
toolUsages?: ToolUsage[]
|
|
161
|
+
/**
|
|
162
|
+
* **조치 제안** — 도구가 실행하지 않고 제안만 한 것들. 실행은 사용자가 버튼으로 한다.
|
|
163
|
+
*
|
|
164
|
+
* 규약: 도구 결과에 `proposed: true` 가 있으면 제안이다(도메인 무관 — board-ai 는 내용을 해석하지
|
|
165
|
+
* 않고 그대로 전달한다). 되돌릴 수 없는 조치를 AI 가 직접 실행하지 않게 하는 경계가 이 채널이다.
|
|
166
|
+
*/
|
|
167
|
+
proposals?: any[]
|
|
168
|
+
/**
|
|
169
|
+
* 접지 경고 — 답이 언급했으나 모델이 받은 근거(프롬프트·보드 문맥·이력·도구 결과)에 없는 식별자.
|
|
170
|
+
*
|
|
171
|
+
* 있으면 그 대상은 **만들어 낸 것일 수 있다**. 답을 막거나 고치지 않고 사용자에게 표시한다 —
|
|
172
|
+
* 판정 규칙·사정거리는 ./grounding 참조. 비면(undefined) 접지 정상.
|
|
173
|
+
*/
|
|
174
|
+
groundingWarnings?: string[]
|
|
136
175
|
}
|
|
137
176
|
|
|
138
177
|
export interface BoardEditPatch {
|
package/translations/en.json
CHANGED
|
@@ -45,5 +45,20 @@
|
|
|
45
45
|
"board-ai.text.copied": "Copied",
|
|
46
46
|
"board-ai.text.mention-not-found": "#{token} not found",
|
|
47
47
|
"board-ai.text.session-tab-label": "Session {n}",
|
|
48
|
-
"board-ai.text.tools-used": "Tools used"
|
|
48
|
+
"board-ai.text.tools-used": "Tools used",
|
|
49
|
+
"board-ai.text.tool-turn": "decision {n}",
|
|
50
|
+
"board-ai.text.tool-rejected-count": "rejected {count}",
|
|
51
|
+
"board-ai.text.tool-folded-count": "folded {count}",
|
|
52
|
+
"board-ai.text.outcome-ok": "read",
|
|
53
|
+
"board-ai.text.outcome-rejected": "rejected",
|
|
54
|
+
"board-ai.text.outcome-queued": "to apply",
|
|
55
|
+
"board-ai.text.outcome-proposed": "proposed",
|
|
56
|
+
"board-ai.text.outcome-folded": "duplicate",
|
|
57
|
+
"board-ai.text.outcome-error": "error",
|
|
58
|
+
"board-ai.text.ungrounded-mention": "Mentions an unverified target — not present in the actual data:",
|
|
59
|
+
"board-ai.text.toggle-system-note": "click to expand",
|
|
60
|
+
"board-ai.button.run-proposal": "run",
|
|
61
|
+
"board-ai.text.proposal-sent": "execution requested",
|
|
62
|
+
"board-ai.text.history-folded": "this conversation grew long — the earlier {count} messages were left out. a new conversation is better for a different topic.",
|
|
63
|
+
"board-ai.text.history-folded-summarized": "this conversation grew long — the earlier {count} messages were folded into a summary. a new conversation is better for a different topic."
|
|
49
64
|
}
|
package/translations/ja.json
CHANGED
|
@@ -44,5 +44,20 @@
|
|
|
44
44
|
"board-ai.text.copied": "コピーしました",
|
|
45
45
|
"board-ai.text.mention-not-found": "#{token} が見つかりません",
|
|
46
46
|
"board-ai.text.session-tab-label": "セッション {n}",
|
|
47
|
-
"board-ai.text.tools-used": "使用したツール"
|
|
47
|
+
"board-ai.text.tools-used": "使用したツール",
|
|
48
|
+
"board-ai.text.tool-turn": "{n} 回目の判断",
|
|
49
|
+
"board-ai.text.tool-rejected-count": "却下 {count}",
|
|
50
|
+
"board-ai.text.tool-folded-count": "重複 {count}",
|
|
51
|
+
"board-ai.text.outcome-ok": "照会",
|
|
52
|
+
"board-ai.text.outcome-rejected": "却下",
|
|
53
|
+
"board-ai.text.outcome-queued": "適用予定",
|
|
54
|
+
"board-ai.text.outcome-proposed": "提案",
|
|
55
|
+
"board-ai.text.outcome-folded": "重複",
|
|
56
|
+
"board-ai.text.outcome-error": "エラー",
|
|
57
|
+
"board-ai.text.ungrounded-mention": "確認できない対象に言及しています — 実データにありません:",
|
|
58
|
+
"board-ai.text.toggle-system-note": "クリックで展開",
|
|
59
|
+
"board-ai.button.run-proposal": "実行",
|
|
60
|
+
"board-ai.text.proposal-sent": "実行を依頼しました",
|
|
61
|
+
"board-ai.text.history-folded": "会話が長くなり、前半の {count} 件は省略されました。別の話題なら新しい会話のほうが適しています。",
|
|
62
|
+
"board-ai.text.history-folded-summarized": "会話が長くなり、前半の {count} 件は要約にまとめられました。別の話題なら新しい会話のほうが適しています。"
|
|
48
63
|
}
|
package/translations/ko.json
CHANGED
|
@@ -23,6 +23,21 @@
|
|
|
23
23
|
"board-ai.text.failed-to-load-history": "이력 로드 실패",
|
|
24
24
|
"board-ai.text.empty-response": "응답이 비어있습니다.",
|
|
25
25
|
"board-ai.text.tools-used": "도구 사용",
|
|
26
|
+
"board-ai.text.tool-turn": "{n}번째 판단",
|
|
27
|
+
"board-ai.text.tool-rejected-count": "거절 {count}",
|
|
28
|
+
"board-ai.text.tool-folded-count": "접힘 {count}",
|
|
29
|
+
"board-ai.text.outcome-ok": "조회",
|
|
30
|
+
"board-ai.text.outcome-rejected": "거절",
|
|
31
|
+
"board-ai.text.outcome-queued": "적용 예정",
|
|
32
|
+
"board-ai.text.outcome-proposed": "제안",
|
|
33
|
+
"board-ai.text.outcome-folded": "중복 접힘",
|
|
34
|
+
"board-ai.text.outcome-error": "오류",
|
|
35
|
+
"board-ai.text.ungrounded-mention": "확인되지 않은 대상을 언급했습니다 — 실제 데이터에 없습니다:",
|
|
36
|
+
"board-ai.text.toggle-system-note": "눌러서 펼치기",
|
|
37
|
+
"board-ai.button.run-proposal": "실행",
|
|
38
|
+
"board-ai.text.proposal-sent": "실행 요청됨",
|
|
39
|
+
"board-ai.text.history-folded": "대화가 길어져 앞부분 {count}개가 생략되었습니다. 다른 주제라면 새 대화가 낫습니다.",
|
|
40
|
+
"board-ai.text.history-folded-summarized": "대화가 길어져 앞부분 {count}개가 요약으로 접혔습니다. 다른 주제라면 새 대화가 낫습니다.",
|
|
26
41
|
|
|
27
42
|
"board-ai.example.create-monitoring-dashboard": "가동률·온도·압력 3개 게이지와 24시간 라인 차트로 모니터링 대시보드",
|
|
28
43
|
"board-ai.example.create-welcome-screen": "큰 'OPERATO' 제목과 시계, 부제로 환영 화면",
|
package/translations/ms.json
CHANGED
|
@@ -44,5 +44,20 @@
|
|
|
44
44
|
"board-ai.text.copied": "Disalin",
|
|
45
45
|
"board-ai.text.mention-not-found": "#{token} tidak dijumpai",
|
|
46
46
|
"board-ai.text.session-tab-label": "Sesi {n}",
|
|
47
|
-
"board-ai.text.tools-used": "Alat yang digunakan"
|
|
47
|
+
"board-ai.text.tools-used": "Alat yang digunakan",
|
|
48
|
+
"board-ai.text.tool-turn": "keputusan {n}",
|
|
49
|
+
"board-ai.text.tool-rejected-count": "ditolak {count}",
|
|
50
|
+
"board-ai.text.tool-folded-count": "pendua {count}",
|
|
51
|
+
"board-ai.text.outcome-ok": "baca",
|
|
52
|
+
"board-ai.text.outcome-rejected": "ditolak",
|
|
53
|
+
"board-ai.text.outcome-queued": "akan digunakan",
|
|
54
|
+
"board-ai.text.outcome-proposed": "dicadangkan",
|
|
55
|
+
"board-ai.text.outcome-folded": "pendua",
|
|
56
|
+
"board-ai.text.outcome-error": "ralat",
|
|
57
|
+
"board-ai.text.ungrounded-mention": "Menyebut sasaran yang tidak disahkan — tiada dalam data sebenar:",
|
|
58
|
+
"board-ai.text.toggle-system-note": "klik untuk kembangkan",
|
|
59
|
+
"board-ai.button.run-proposal": "jalankan",
|
|
60
|
+
"board-ai.text.proposal-sent": "pelaksanaan diminta",
|
|
61
|
+
"board-ai.text.history-folded": "perbualan ini menjadi panjang — {count} mesej terawal ditinggalkan. perbualan baharu lebih sesuai untuk topik lain.",
|
|
62
|
+
"board-ai.text.history-folded-summarized": "perbualan ini menjadi panjang — {count} mesej terawal diringkaskan. perbualan baharu lebih sesuai untuk topik lain."
|
|
48
63
|
}
|
package/translations/zh.json
CHANGED
|
@@ -44,5 +44,20 @@
|
|
|
44
44
|
"board-ai.text.copied": "已复制",
|
|
45
45
|
"board-ai.text.mention-not-found": "未找到 #{token}",
|
|
46
46
|
"board-ai.text.session-tab-label": "会话 {n}",
|
|
47
|
-
"board-ai.text.tools-used": "使用的工具"
|
|
47
|
+
"board-ai.text.tools-used": "使用的工具",
|
|
48
|
+
"board-ai.text.tool-turn": "第 {n} 次判断",
|
|
49
|
+
"board-ai.text.tool-rejected-count": "拒绝 {count}",
|
|
50
|
+
"board-ai.text.tool-folded-count": "折叠 {count}",
|
|
51
|
+
"board-ai.text.outcome-ok": "查询",
|
|
52
|
+
"board-ai.text.outcome-rejected": "拒绝",
|
|
53
|
+
"board-ai.text.outcome-queued": "待应用",
|
|
54
|
+
"board-ai.text.outcome-proposed": "提案",
|
|
55
|
+
"board-ai.text.outcome-folded": "重复",
|
|
56
|
+
"board-ai.text.outcome-error": "错误",
|
|
57
|
+
"board-ai.text.ungrounded-mention": "提到了未经确认的对象 — 实际数据中不存在:",
|
|
58
|
+
"board-ai.text.toggle-system-note": "点击展开",
|
|
59
|
+
"board-ai.button.run-proposal": "执行",
|
|
60
|
+
"board-ai.text.proposal-sent": "已请求执行",
|
|
61
|
+
"board-ai.text.history-folded": "对话变长,前面 {count} 条已省略。若是另一个话题,新建对话更合适。",
|
|
62
|
+
"board-ai.text.history-folded-summarized": "对话变长,前面 {count} 条已折叠为摘要。若是另一个话题,新建对话更合适。"
|
|
48
63
|
}
|