@things-factory/figure-service 10.1.170 → 10.1.171
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-propose-steps.d.ts +7 -0
- package/dist-server/service/figure/figure-propose-steps.js +25 -2
- package/dist-server/service/figure/figure-propose-steps.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/server/service/figure/figure-propose-steps.test.ts +18 -1
- package/server/service/figure/figure-propose-steps.ts +25 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/figure-service",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.171",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"jszip": "^3.10.1",
|
|
39
39
|
"koa-router": "^7.4.0"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "e88536db0bc3cbb759fe58f9efeef66a67fef2c3"
|
|
42
42
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { FIGURE_PROPOSAL_GRAMMAR, addFigureBox, applyFigureAuthoring, applyFigureProposal, createFigureAsset, inspectFigureAsset, proposeFigureOccupancy } from '@hatiolab/figure-model'
|
|
9
9
|
import { AIAnswerNotJSON, type AIClient } from '@things-factory/ai-client-base'
|
|
10
10
|
|
|
11
|
-
import { ProposeFigureFailure, judgeFigureAnswer, proposalFailureForPerson, proposeFigureSteps, rulesPromptFigure } from './figure-propose-steps'
|
|
11
|
+
import { ProposeFigureFailure, WORKED_EXAMPLE, judgeFigureAnswer, proposalFailureForPerson, proposeFigureSteps, rulesPromptFigure } from './figure-propose-steps'
|
|
12
12
|
|
|
13
13
|
function stubClient(answers: unknown[]): AIClient & { calls: number; sent: any[][]; system?: string } {
|
|
14
14
|
const client = {
|
|
@@ -61,6 +61,23 @@ describe('the model is told the kernel\'s commands and the open draft', () => {
|
|
|
61
61
|
frame rail by hand, sixty steps, and fastened a rail twice (ATTACH_REPLACED at steps[59]); another named a part it
|
|
62
62
|
had not added. Both are rules of writing, so they are taught with the rules.
|
|
63
63
|
*/
|
|
64
|
+
/*
|
|
65
|
+
Three walks on :3300 (2026-10-16) stopped at three fastening rules in turn -- a part not added, flush on the mounting
|
|
66
|
+
plane, a face that does not meet -- each refusal saying what to do, and none put right in three tries. A rule a line
|
|
67
|
+
at a time did not end it; one whole answer the kernel takes shows the rules together. It is held to the kernel here,
|
|
68
|
+
on the path an answer takes, so it cannot teach what the kernel refuses.
|
|
69
|
+
*/
|
|
70
|
+
it('shows one whole answer, and that answer is one the kernel and the gate take', () => {
|
|
71
|
+
expect(rulesPromptFigure()).toContain(JSON.stringify({ steps: WORKED_EXAMPLE }))
|
|
72
|
+
const judged = judgeFigureAnswer(createFigureAsset('Roller conveyor'), { steps: WORKED_EXAMPLE }, false)
|
|
73
|
+
expect(judged.reasons).toEqual([])
|
|
74
|
+
expect(judged.source!.appearance.map(a => a.target)).toEqual(['frame', 'support', 'roller'])
|
|
75
|
+
const kinds = WORKED_EXAMPLE.map(step => step.kind)
|
|
76
|
+
expect(kinds).toContain('make-repeat')
|
|
77
|
+
expect(kinds.at(-1)).toBe('fit-room')
|
|
78
|
+
expect(WORKED_EXAMPLE.filter(step => step.kind === 'attach' && 'plane' in (step as any).to).every(step => !('facing' in step))).toBe(true)
|
|
79
|
+
})
|
|
80
|
+
|
|
64
81
|
it('teaches a row of the same part as one part repeated, and each part fastened once', () => {
|
|
65
82
|
const rules = rulesPromptFigure()
|
|
66
83
|
expect(rules).toMatch(/same part .*make-repeat/)
|
|
@@ -77,6 +77,25 @@ export function proposalFailureForPerson(failure: ProposeFigureFailure, t: (key:
|
|
|
77
77
|
return [t('error.figure-proposal-failed', { defaultValue: failure.message }), ...failure.reasons].join('\n')
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* One whole answer the kernel and the gate take: a roller conveyor on two end supports. Three walks on :3300
|
|
82
|
+
* (2026-10-16) stopped at three fastening rules in turn, each refusal saying what to do and none put right; one answer
|
|
83
|
+
* shows them together -- the plane taken without facing, a part fastened under another, a row made once. Held to the
|
|
84
|
+
* kernel by its test, on the path an answer takes.
|
|
85
|
+
*/
|
|
86
|
+
export const WORKED_EXAMPLE: FigureProposalStep[] = [
|
|
87
|
+
{ kind: 'add-part', part: { id: 'frame', kind: 'box', dimensions: { width: 2000, height: 100, depth: 600 } } },
|
|
88
|
+
{ kind: 'attach', part: 'frame', face: 'bottom', to: { plane: 'mounting-plane' }, gap: 700 },
|
|
89
|
+
{ kind: 'add-part', part: { id: 'support', kind: 'box', dimensions: { width: 80, height: 700, depth: 560 } } },
|
|
90
|
+
{ kind: 'attach', part: 'support', face: 'top', to: { part: 'frame', face: 'bottom' }, align: { x: 'min' } },
|
|
91
|
+
{ kind: 'make-repeat', part: 'support', axis: 'x', pitch: 1920, count: 2 },
|
|
92
|
+
{ kind: 'add-part', part: { id: 'roller', kind: 'box', dimensions: { width: 60, height: 60, depth: 560 } } },
|
|
93
|
+
{ kind: 'attach', part: 'roller', face: 'bottom', to: { part: 'frame', face: 'top' } },
|
|
94
|
+
{ kind: 'make-repeat', part: 'roller', axis: 'x', pitch: 160 },
|
|
95
|
+
{ kind: 'set-material', target: 'frame', material: { token: 'palette.frame' }, palette: { 'palette.frame': '#5b6770' } },
|
|
96
|
+
{ kind: 'fit-room', placement: 'floor' }
|
|
97
|
+
] as FigureProposalStep[]
|
|
98
|
+
|
|
80
99
|
/** The rules and the words, all from figure-model's constants. */
|
|
81
100
|
export function rulesPromptFigure(): string {
|
|
82
101
|
return [
|
|
@@ -100,7 +119,12 @@ export function rulesPromptFigure(): string {
|
|
|
100
119
|
'When revising, write only the commands the request needs. Everything not touched stays as it is.',
|
|
101
120
|
'',
|
|
102
121
|
'The commands (shape, then what it means):',
|
|
103
|
-
...FIGURE_PROPOSAL_GRAMMAR.map(word => `- ${word.shape}\n ${word.means}`)
|
|
122
|
+
...FIGURE_PROPOSAL_GRAMMAR.map(word => `- ${word.shape}\n ${word.means}`),
|
|
123
|
+
'',
|
|
124
|
+
'One whole answer the modeller takes, for a new roller conveyor -- an example of the form, not of the figure asked for:',
|
|
125
|
+
'the frame stands 700 mm up on the mounting plane, a support is fastened under it at one end and repeated to two, a',
|
|
126
|
+
'roller is fastened on top and repeated along it.',
|
|
127
|
+
JSON.stringify({ steps: WORKED_EXAMPLE })
|
|
104
128
|
].join('\n')
|
|
105
129
|
}
|
|
106
130
|
|