newo 3.6.1 → 3.6.2
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/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.6.2] - 2026-04-23
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`attributes.yaml` YAML escaping**: The attribute serializer previously ran `.replace(/\\"/g, '"')` as a "prettify" post-processing step, which stripped legitimate YAML escape characters from double-quoted scalars. Values containing double quotes (e.g. `["+37410333310"]`) were written as invalid YAML like `value: "["+37410333310"]"` — rejected by `yaml.load` with `bad indentation of a mapping entry`. This made `newo push --format newo_v2` unable to parse customer/project attribute files at all, and long compiled values (e.g. AMI) broke on the first embedded quote. The serializer now uses the existing `patchYamlToPyyaml` post-processor (already used on the V2 path) to convert JSON-like double-quoted values to single-quoted form (`value: '["+37410333310"]'`) and handle long-line wrapping in pyyaml style. Fix applied in both `src/sync/attributes.ts` and `src/domain/strategies/sync/AttributeSyncStrategy.ts`. Added 11 round-trip regression tests.
|
|
15
|
+
|
|
10
16
|
## [3.6.1] - 2026-04-14
|
|
11
17
|
|
|
12
18
|
### Documentation
|
|
@@ -994,7 +1000,8 @@ Another Item: $Price [Modifiers: modifier3]
|
|
|
994
1000
|
- GitHub Actions CI/CD integration
|
|
995
1001
|
- Robust authentication with token refresh
|
|
996
1002
|
|
|
997
|
-
[Unreleased]: https://github.com/sabbah13/newo-cli/compare/v3.
|
|
1003
|
+
[Unreleased]: https://github.com/sabbah13/newo-cli/compare/v3.6.2...HEAD
|
|
1004
|
+
[3.6.2]: https://github.com/sabbah13/newo-cli/compare/v3.6.1...v3.6.2
|
|
998
1005
|
[3.3.0]: https://github.com/sabbah13/newo-cli/compare/v3.2.0...v3.3.0
|
|
999
1006
|
[3.2.0]: https://github.com/sabbah13/newo-cli/compare/v3.1.0...v3.2.0
|
|
1000
1007
|
[3.1.0]: https://github.com/sabbah13/newo-cli/compare/v3.0.0...v3.1.0
|
|
@@ -14,6 +14,7 @@ import yaml from 'js-yaml';
|
|
|
14
14
|
import path from 'path';
|
|
15
15
|
import { getCustomerAttributes, getProjectAttributes, updateCustomerAttribute, updateProjectAttribute, listProjects } from '../../../api.js';
|
|
16
16
|
import { writeFileSafe, customerAttributesPath, customerAttributesMapPath } from '../../../fsutil.js';
|
|
17
|
+
import { patchYamlToPyyaml } from '../../../format/yaml-patch.js';
|
|
17
18
|
import { sha256, saveHashes, loadHashes } from '../../../hash.js';
|
|
18
19
|
/**
|
|
19
20
|
* AttributeSyncStrategy - Handles attribute synchronization
|
|
@@ -171,18 +172,20 @@ export class AttributeSyncStrategy {
|
|
|
171
172
|
...attr,
|
|
172
173
|
value_type: `__ENUM_PLACEHOLDER_${attr.value_type}__`
|
|
173
174
|
}));
|
|
175
|
+
// Emit YAML without folding/wrapping; patchYamlToPyyaml handles long-line
|
|
176
|
+
// wrapping and converts JSON-like double-quoted values to single-quoted
|
|
177
|
+
// (so strings containing `"` stay valid YAML on reload).
|
|
174
178
|
let yamlContent = yaml.dump({ attributes: attributesWithPlaceholders }, {
|
|
175
179
|
indent: 2,
|
|
176
180
|
quotingType: '"',
|
|
177
181
|
forceQuotes: false,
|
|
178
|
-
lineWidth:
|
|
182
|
+
lineWidth: -1,
|
|
179
183
|
noRefs: true,
|
|
180
184
|
sortKeys: false,
|
|
181
|
-
flowLevel: -1
|
|
185
|
+
flowLevel: -1,
|
|
182
186
|
});
|
|
183
|
-
// Replace placeholders with enum syntax
|
|
184
187
|
yamlContent = yamlContent.replace(/__ENUM_PLACEHOLDER_(\w+)__/g, '!enum "AttributeValueTypes.$1"');
|
|
185
|
-
yamlContent = yamlContent
|
|
188
|
+
yamlContent = patchYamlToPyyaml(yamlContent);
|
|
186
189
|
return yamlContent;
|
|
187
190
|
}
|
|
188
191
|
/**
|
package/dist/sync/attributes.js
CHANGED
|
@@ -6,6 +6,7 @@ import { writeFileSafe, customerAttributesPath, customerAttributesMapPath, custo
|
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
8
|
import yaml from 'js-yaml';
|
|
9
|
+
import { patchYamlToPyyaml } from '../format/yaml-patch.js';
|
|
9
10
|
/**
|
|
10
11
|
* Save customer attributes to YAML format and return content for hashing
|
|
11
12
|
*/
|
|
@@ -55,23 +56,22 @@ export async function saveCustomerAttributes(client, customer, verbose = false)
|
|
|
55
56
|
const attributesYaml = {
|
|
56
57
|
attributes: cleanAttributes
|
|
57
58
|
};
|
|
58
|
-
//
|
|
59
|
+
// Emit YAML without folding/wrapping; patchYamlToPyyaml handles long-line
|
|
60
|
+
// wrapping and converts JSON-like double-quoted values to single-quoted
|
|
61
|
+
// (so strings containing `"` stay valid YAML on reload).
|
|
59
62
|
let yamlContent = yaml.dump(attributesYaml, {
|
|
60
63
|
indent: 2,
|
|
61
64
|
quotingType: '"',
|
|
62
65
|
forceQuotes: false,
|
|
63
|
-
lineWidth:
|
|
66
|
+
lineWidth: -1,
|
|
64
67
|
noRefs: true,
|
|
65
68
|
sortKeys: false,
|
|
66
|
-
flowLevel: -1,
|
|
67
|
-
styles: {
|
|
68
|
-
'!!str': 'folded' // Use folded style for better line wrapping of long strings
|
|
69
|
-
}
|
|
69
|
+
flowLevel: -1,
|
|
70
70
|
});
|
|
71
|
-
// Post-process to fix enum format
|
|
71
|
+
// Post-process to fix enum format
|
|
72
72
|
yamlContent = yamlContent.replace(/__ENUM_PLACEHOLDER_(\w+)__/g, '!enum "AttributeValueTypes.$1"');
|
|
73
|
-
//
|
|
74
|
-
yamlContent = yamlContent
|
|
73
|
+
// Convert JSON-like double-quoted values to single-quoted and wrap long lines
|
|
74
|
+
yamlContent = patchYamlToPyyaml(yamlContent);
|
|
75
75
|
// Save all files: attributes.yaml, ID mapping, and backup for diff tracking
|
|
76
76
|
await writeFileSafe(customerAttributesPath(customer.idn), yamlContent);
|
|
77
77
|
await writeFileSafe(customerAttributesMapPath(customer.idn), JSON.stringify(idMapping, null, 2));
|
|
@@ -139,19 +139,19 @@ export async function saveProjectAttributes(client, customer, projectId, project
|
|
|
139
139
|
const attributesYaml = {
|
|
140
140
|
attributes: cleanAttributes
|
|
141
141
|
};
|
|
142
|
-
//
|
|
142
|
+
// Emit YAML without folding/wrapping; patchYamlToPyyaml handles long-line
|
|
143
|
+
// wrapping and converts JSON-like double-quoted values to single-quoted.
|
|
143
144
|
let yamlContent = yaml.dump(attributesYaml, {
|
|
144
145
|
indent: 2,
|
|
145
146
|
quotingType: '"',
|
|
146
147
|
forceQuotes: false,
|
|
147
|
-
lineWidth:
|
|
148
|
+
lineWidth: -1,
|
|
148
149
|
noRefs: true,
|
|
149
150
|
sortKeys: false,
|
|
150
|
-
flowLevel: -1
|
|
151
|
+
flowLevel: -1,
|
|
151
152
|
});
|
|
152
|
-
// Post-process to fix enum format
|
|
153
153
|
yamlContent = yamlContent.replace(/__ENUM_PLACEHOLDER_(\w+)__/g, '!enum "AttributeValueTypes.$1"');
|
|
154
|
-
yamlContent = yamlContent
|
|
154
|
+
yamlContent = patchYamlToPyyaml(yamlContent);
|
|
155
155
|
// Save to project directory
|
|
156
156
|
const customerDir = path.join(process.cwd(), 'newo_customers', customer.idn);
|
|
157
157
|
const projectDir = path.join(customerDir, 'projects', projectIdn);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newo",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.2",
|
|
4
4
|
"description": "NEWO CLI: Professional command-line tool with modular architecture for NEWO AI Agent development. Features account migration, integration management, webhook automation, AKB knowledge base, project attributes, sandbox testing, IDN-based file management, real-time progress tracking, intelligent sync operations, and comprehensive multi-customer support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
customerAttributesPath,
|
|
39
39
|
customerAttributesMapPath
|
|
40
40
|
} from '../../../fsutil.js';
|
|
41
|
+
import { patchYamlToPyyaml } from '../../../format/yaml-patch.js';
|
|
41
42
|
import { sha256, saveHashes, loadHashes } from '../../../hash.js';
|
|
42
43
|
|
|
43
44
|
/**
|
|
@@ -251,19 +252,21 @@ export class AttributeSyncStrategy implements ISyncStrategy<CustomerAttributesRe
|
|
|
251
252
|
value_type: `__ENUM_PLACEHOLDER_${attr.value_type}__`
|
|
252
253
|
}));
|
|
253
254
|
|
|
255
|
+
// Emit YAML without folding/wrapping; patchYamlToPyyaml handles long-line
|
|
256
|
+
// wrapping and converts JSON-like double-quoted values to single-quoted
|
|
257
|
+
// (so strings containing `"` stay valid YAML on reload).
|
|
254
258
|
let yamlContent = yaml.dump({ attributes: attributesWithPlaceholders }, {
|
|
255
259
|
indent: 2,
|
|
256
260
|
quotingType: '"',
|
|
257
261
|
forceQuotes: false,
|
|
258
|
-
lineWidth:
|
|
262
|
+
lineWidth: -1,
|
|
259
263
|
noRefs: true,
|
|
260
264
|
sortKeys: false,
|
|
261
|
-
flowLevel: -1
|
|
265
|
+
flowLevel: -1,
|
|
262
266
|
});
|
|
263
267
|
|
|
264
|
-
// Replace placeholders with enum syntax
|
|
265
268
|
yamlContent = yamlContent.replace(/__ENUM_PLACEHOLDER_(\w+)__/g, '!enum "AttributeValueTypes.$1"');
|
|
266
|
-
yamlContent = yamlContent
|
|
269
|
+
yamlContent = patchYamlToPyyaml(yamlContent);
|
|
267
270
|
|
|
268
271
|
return yamlContent;
|
|
269
272
|
}
|
package/src/sync/attributes.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import path from 'path';
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import yaml from 'js-yaml';
|
|
14
|
+
import { patchYamlToPyyaml } from '../format/yaml-patch.js';
|
|
14
15
|
import type { AxiosInstance } from 'axios';
|
|
15
16
|
import type { CustomerConfig } from '../types.js';
|
|
16
17
|
|
|
@@ -72,25 +73,24 @@ export async function saveCustomerAttributes(
|
|
|
72
73
|
attributes: cleanAttributes
|
|
73
74
|
};
|
|
74
75
|
|
|
75
|
-
//
|
|
76
|
+
// Emit YAML without folding/wrapping; patchYamlToPyyaml handles long-line
|
|
77
|
+
// wrapping and converts JSON-like double-quoted values to single-quoted
|
|
78
|
+
// (so strings containing `"` stay valid YAML on reload).
|
|
76
79
|
let yamlContent = yaml.dump(attributesYaml, {
|
|
77
80
|
indent: 2,
|
|
78
81
|
quotingType: '"',
|
|
79
82
|
forceQuotes: false,
|
|
80
|
-
lineWidth:
|
|
83
|
+
lineWidth: -1,
|
|
81
84
|
noRefs: true,
|
|
82
85
|
sortKeys: false,
|
|
83
|
-
flowLevel: -1,
|
|
84
|
-
styles: {
|
|
85
|
-
'!!str': 'folded' // Use folded style for better line wrapping of long strings
|
|
86
|
-
}
|
|
86
|
+
flowLevel: -1,
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
// Post-process to fix enum format
|
|
89
|
+
// Post-process to fix enum format
|
|
90
90
|
yamlContent = yamlContent.replace(/__ENUM_PLACEHOLDER_(\w+)__/g, '!enum "AttributeValueTypes.$1"');
|
|
91
91
|
|
|
92
|
-
//
|
|
93
|
-
yamlContent = yamlContent
|
|
92
|
+
// Convert JSON-like double-quoted values to single-quoted and wrap long lines
|
|
93
|
+
yamlContent = patchYamlToPyyaml(yamlContent);
|
|
94
94
|
|
|
95
95
|
// Save all files: attributes.yaml, ID mapping, and backup for diff tracking
|
|
96
96
|
await writeFileSafe(customerAttributesPath(customer.idn), yamlContent);
|
|
@@ -172,20 +172,20 @@ export async function saveProjectAttributes(
|
|
|
172
172
|
attributes: cleanAttributes
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
//
|
|
175
|
+
// Emit YAML without folding/wrapping; patchYamlToPyyaml handles long-line
|
|
176
|
+
// wrapping and converts JSON-like double-quoted values to single-quoted.
|
|
176
177
|
let yamlContent = yaml.dump(attributesYaml, {
|
|
177
178
|
indent: 2,
|
|
178
179
|
quotingType: '"',
|
|
179
180
|
forceQuotes: false,
|
|
180
|
-
lineWidth:
|
|
181
|
+
lineWidth: -1,
|
|
181
182
|
noRefs: true,
|
|
182
183
|
sortKeys: false,
|
|
183
|
-
flowLevel: -1
|
|
184
|
+
flowLevel: -1,
|
|
184
185
|
});
|
|
185
186
|
|
|
186
|
-
// Post-process to fix enum format
|
|
187
187
|
yamlContent = yamlContent.replace(/__ENUM_PLACEHOLDER_(\w+)__/g, '!enum "AttributeValueTypes.$1"');
|
|
188
|
-
yamlContent = yamlContent
|
|
188
|
+
yamlContent = patchYamlToPyyaml(yamlContent);
|
|
189
189
|
|
|
190
190
|
// Save to project directory
|
|
191
191
|
const customerDir = path.join(process.cwd(), 'newo_customers', customer.idn);
|