@things-factory/ai-assistant 10.1.104 → 10.1.107

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/ai-assistant",
3
- "version": "10.1.104",
3
+ "version": "10.1.107",
4
4
  "main": "dist-server/index.js",
5
5
  "things-factory": true,
6
6
  "author": "heartyoh",
@@ -34,11 +34,11 @@
34
34
  "@operato/shell": "^10.0.0",
35
35
  "@operato/styles": "^10.0.0",
36
36
  "@things-factory/ai-client-base": "^10.1.81",
37
- "@things-factory/apptool-base": "^10.1.79",
38
- "@things-factory/attachment-base": "^10.1.79",
39
- "@things-factory/auth-base": "^10.1.79",
37
+ "@things-factory/apptool-base": "^10.1.106",
38
+ "@things-factory/attachment-base": "^10.1.107",
39
+ "@things-factory/auth-base": "^10.1.107",
40
40
  "@things-factory/env": "^10.1.20",
41
- "@things-factory/shell": "^10.1.79",
41
+ "@things-factory/shell": "^10.1.106",
42
42
  "dompurify": "^3.0.0",
43
43
  "graphql-scalars": "^1.22.0",
44
44
  "graphql-tag": "^2.12.6",
@@ -51,5 +51,5 @@
51
51
  "copyfiles": "^2.4.1",
52
52
  "rimraf": "^5.0.0"
53
53
  },
54
- "gitHead": "0d05c7573220c6da2dec2654a4b86d7bd8e3c4fb"
54
+ "gitHead": "65a3d5889e687d8122a65f029b926b1a4769d1c0"
55
55
  }
@@ -110,6 +110,13 @@ describe('the card', () => {
110
110
  expect(rows[0].issues).toEqual([{ field: 'spentDate', code: 'not-changeable', blocking: false }, { code: 'no-change', blocking: true }])
111
111
  expect(rows[1].issues).toEqual([{ field: 'category', code: 'not-in-list', params: { values: ['교통비', '회의비'] }, blocking: true }])
112
112
  })
113
+
114
+ it('★ a field restated as it already is is not a change - not shown, not written (the model sent the name back with the note)', async () => {
115
+ const result: any = await proposeChanges(expense, { changes: [{ ref: 'l1', values: { merchant: '카카오T', amount: '12400', category: '회의비' } }] }, { host: {} }, run)
116
+ expect(result.rows[0]).toMatchObject({ before: { category: '교통비' }, values: { category: '회의비' }, issues: [] })
117
+ expect(Object.keys(result.rows[0].values)).toEqual(['category'])
118
+ expect(result.columns.map((one: any) => one.name)).toEqual(['category'])
119
+ })
113
120
  })
114
121
 
115
122
  describe('changing what the person pressed', () => {
@@ -115,8 +115,12 @@ export function changeRows(target: EntryTarget, picked: { id: string; via: Chang
115
115
  if (record) before[name] = record[name] ?? null
116
116
  }
117
117
  if (!record) issues.push({ code: 'record-not-found', blocking: true })
118
- else if (Object.keys(values).length && Object.keys(values).every(name => sameFieldValue(fields.get(name)!, before[name], values[name])))
119
- issues.push({ code: 'no-change', blocking: true })
118
+ else {
119
+ /* A field the model restated as it already is does not change - the card shows it as no change, and it is not written. */
120
+ const same = Object.keys(values).filter(name => fields.has(name) && !issues.some(issue => issue.field === name) && sameFieldValue(fields.get(name)!, before[name], values[name]))
121
+ if (same.length && same.length === Object.keys(values).length) issues.push({ code: 'no-change', blocking: true })
122
+ else for (const name of same) delete values[name], delete before[name]
123
+ }
120
124
  if (!Object.keys(values).length && !issues.some(issue => issue.blocking)) issues.push({ code: 'nothing-to-change', blocking: true })
121
125
  return { index, id: one.id, via: one.via, ...(record && target.update?.labelOf ? { label: target.update.labelOf(record) } : {}), before, values, issues }
122
126
  })
@@ -11,6 +11,7 @@ import {
11
11
  entryOutcomeNote,
12
12
  entryProposalHandler,
13
13
  entryReadyCount,
14
+ entryTitle,
14
15
  latestEntryKeys,
15
16
  type EntryApplyAnswer
16
17
  } from '../client/utils/entry-proposal'
@@ -21,6 +22,24 @@ const t = (key: string, options: any = {}) =>
21
22
  const card = (key: string, target = 'office.expense-line', rows: any[] = []) => ({ key, kind: 'entry', target, rows })
22
23
 
23
24
  describe('the entry card', () => {
25
+ it('★ is titled by its kind - a 수정안 is never titled as a 입력안', () => {
26
+ const named = (key: string, options: any = {}) => (key === 'label.office-entry-counterparty' ? 'counterparty' : t(key, options))
27
+ expect(entryTitle({ kind: 'entry', target: 'office.counterparty', labelKey: 'label.office-entry-counterparty', rows: [] }, named)).toBe('counterparty to enter')
28
+ expect(entryTitle({ kind: 'entry', op: 'update', target: 'office.counterparty', labelKey: 'label.office-entry-counterparty', rows: [] }, named)).toBe('counterparty to change')
29
+ })
30
+
31
+ it('★ every target label names the record only - the card adds 입력안 or 수정안', () => {
32
+ /* The framework's own declarers; the applications hold the same rule in their translations. */
33
+ const offending: string[] = []
34
+ for (const root of ['../../ops-master', '../../organization', '../../i18n-base'])
35
+ for (const lang of ['ko', 'ja', 'zh', 'ms']) {
36
+ const table: Record<string, string> = JSON.parse(readFileSync(join(__dirname, root, 'translations', `${lang}.json`), 'utf8'))
37
+ for (const [key, value] of Object.entries(table))
38
+ if (/^label\.[a-z0-9-]+-entry-/.test(key) && /입력안|수정안|入力案|录入方案|cadangan/.test(value)) offending.push(`${root}/${lang}: ${key}`)
39
+ }
40
+ expect(offending).toEqual([])
41
+ })
42
+
24
43
  it('★ counts only the rows that will go in', () => {
25
44
  const p = card('k', undefined, [
26
45
  { index: 0, values: {}, sources: [], issues: [] },
@@ -254,6 +254,8 @@
254
254
  "ai-assistant.workspace.contains-metrics": "{count} figures",
255
255
  "ai-assistant.workspace.contains-steps": "{count} progress",
256
256
  "ai-assistant.entry.change": "change {count} records",
257
+ "ai-assistant.entry.title-create": "{name} to enter",
258
+ "ai-assistant.entry.title-update": "{name} to change",
257
259
  "ai-assistant.entry.changed": "changed {count} records.",
258
260
  "ai-assistant.entry.changed-none": "no record was changed.",
259
261
  "ai-assistant.entry.changes": "{count} records",
@@ -254,6 +254,8 @@
254
254
  "ai-assistant.workspace.contains-metrics": "指標 {count}",
255
255
  "ai-assistant.workspace.contains-steps": "経過 {count}",
256
256
  "ai-assistant.entry.change": "{count}件を修正",
257
+ "ai-assistant.entry.title-create": "{name}の入力案",
258
+ "ai-assistant.entry.title-update": "{name}の修正案",
257
259
  "ai-assistant.entry.changed": "{count}件を修正しました。",
258
260
  "ai-assistant.entry.changed-none": "修正された記録はありません。",
259
261
  "ai-assistant.entry.changes": "{count}件",
@@ -254,6 +254,8 @@
254
254
  "ai-assistant.workspace.contains-metrics": "수치 {count}",
255
255
  "ai-assistant.workspace.contains-steps": "경과 {count}",
256
256
  "ai-assistant.entry.change": "{count}건 고치기",
257
+ "ai-assistant.entry.title-create": "{name} 입력안",
258
+ "ai-assistant.entry.title-update": "{name} 수정안",
257
259
  "ai-assistant.entry.changed": "{count}건을 고쳤습니다.",
258
260
  "ai-assistant.entry.changed-none": "고친 기록이 없습니다.",
259
261
  "ai-assistant.entry.changes": "{count}건",
@@ -254,6 +254,8 @@
254
254
  "ai-assistant.workspace.contains-metrics": "{count} angka",
255
255
  "ai-assistant.workspace.contains-steps": "{count} kemajuan",
256
256
  "ai-assistant.entry.change": "ubah {count} rekod",
257
+ "ai-assistant.entry.title-create": "cadangan kemasukan {name}",
258
+ "ai-assistant.entry.title-update": "cadangan perubahan {name}",
257
259
  "ai-assistant.entry.changed": "{count} rekod diubah.",
258
260
  "ai-assistant.entry.changed-none": "tiada rekod diubah.",
259
261
  "ai-assistant.entry.changes": "{count} rekod",
@@ -254,6 +254,8 @@
254
254
  "ai-assistant.workspace.contains-metrics": "指标 {count}",
255
255
  "ai-assistant.workspace.contains-steps": "进度 {count}",
256
256
  "ai-assistant.entry.change": "修改{count}条",
257
+ "ai-assistant.entry.title-create": "{name}录入方案",
258
+ "ai-assistant.entry.title-update": "{name}修改方案",
257
259
  "ai-assistant.entry.changed": "已修改{count}条。",
258
260
  "ai-assistant.entry.changed-none": "未修改任何记录。",
259
261
  "ai-assistant.entry.changes": "{count}条",