newo 1.6.0 → 1.7.0

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
@@ -5,6 +5,100 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.7.0] - 2025-09-15
9
+
10
+ ### Added
11
+ - **Customer Attributes Synchronization**: Complete pull/push functionality for customer attributes
12
+ - `GET /api/v1/bff/customer/attributes?include_hidden=true` - Fetches all 233 customer attributes including hidden system attributes
13
+ - `PUT /api/v1/customer/attributes/{attributeId}` - Updates individual customer attributes
14
+ - Saves to `newo_customers/{customerIdn}/attributes.yaml` in customer root directory
15
+ - YAML format matches reference specification exactly with literal blocks, enum types, and proper multi-line formatting
16
+ - Separate ID mapping stored in `.newo/{customerIdn}/attributes-map.json` for push operations
17
+ - Integrated into existing `pull` and `push` commands seamlessly
18
+ - Full TypeScript type safety with `CustomerAttribute` and `CustomerAttributesResponse` interfaces
19
+
20
+ ### Enhanced
21
+ - **YAML Format Compliance**: Perfect format matching with reference files
22
+ - Literal block scalars (`|-`) for multi-line strings
23
+ - Proper enum format (`!enum "AttributeValueTypes.string"`)
24
+ - Complex JSON string formatting with proper line breaks
25
+ - No escaped quotes in output for better readability
26
+ - **Metadata Generation**: Removed legacy JSON metadata files, YAML-only approach
27
+ - Eliminates redundant `metadata.json` files
28
+ - Cleaner file structure with single source of truth
29
+ - Improved performance with fewer file operations
30
+
31
+ ### Technical
32
+ - **API Layer**: Added `updateCustomerAttribute()` and enhanced `getCustomerAttributes()` with `includeHidden` parameter
33
+ - **Sync Engine**: Integrated attributes handling into `pullAll()` and `pushChanged()` functions
34
+ - **File System**: Added `customerAttributesPath()` and `customerAttributesMapPath()` utilities
35
+ - **Type Safety**: Extended type definitions with proper customer attribute interfaces
36
+ - **Error Handling**: Comprehensive error handling for attributes operations with graceful fallbacks
37
+
38
+ ## [1.6.1] - 2025-09-13
39
+
40
+ ### Fixed
41
+ - **YAML Enum Formatting**: Fixed enum formatting in `flows.yaml` generation to properly handle NEWO enum types
42
+ - Corrected enum value serialization from quoted strings to proper YAML enum format
43
+ - Fixed issue where enum values like `!enum "RunnerType.guidance"` were incorrectly quoted
44
+ - Ensures generated `flows.yaml` files are properly formatted for NEWO platform consumption
45
+
46
+ ### Enhanced
47
+ - **ES Module Support**: Added `"type": "module"` to package.json for proper ES module handling
48
+ - Resolves Node.js warnings about module type detection
49
+ - Improves performance by eliminating module type guessing
50
+ - Ensures consistent ES module behavior across all environments
51
+
52
+ ## [1.6.0] - 2025-09-13
53
+
54
+ ### Added
55
+ - **Multi-Customer Auto-Pull**: Revolutionary workflow improvement for multi-customer environments
56
+ - `newo pull` now automatically pulls from ALL customers when no default customer is set
57
+ - Eliminates the need to specify `--customer` flag or set `NEWO_DEFAULT_CUSTOMER` for bulk operations
58
+ - Maintains backward compatibility - individual customer selection still works with `--customer` flag
59
+ - Smart detection: single customer setup works as before, multi-customer setup auto-pulls all
60
+ - **Publishing Infrastructure**: Complete automated publishing system for professional releases
61
+ - `scripts/publish-github.sh`: Automated GitHub publishing with releases, tags, and version management
62
+ - `scripts/publish-npm.sh`: Automated NPM publishing with validation and safety checks
63
+ - Comprehensive Makefile with 40+ commands for development and publishing workflows
64
+ - Version bump helpers (patch/minor/major) with semantic versioning support
65
+ - **Enhanced Documentation**: Professional publishing and development documentation
66
+ - Complete "Publishing & Release Management" section with step-by-step workflows
67
+ - "Local Testing" section with comprehensive testing procedures
68
+ - Makefile command reference with organized development workflows
69
+ - Troubleshooting guides for common development and publishing issues
70
+
71
+ ### Enhanced
72
+ - **Customer Configuration Logic**: New functions for flexible customer handling
73
+ - `tryGetDefaultCustomer()`: Non-throwing version that returns null for multi-customer scenarios
74
+ - `getAllCustomers()`: Returns array of all configured customers for batch operations
75
+ - Improved error handling and user feedback for customer selection scenarios
76
+ - **CLI User Experience**: Enhanced command behavior and help documentation
77
+ - Updated help text to reflect auto-pull behavior: "uses default or all for pull"
78
+ - Clear progress indicators for multi-customer operations
79
+ - Better error messages and troubleshooting guidance
80
+ - **Development Workflow**: Professional development and publishing infrastructure
81
+ - Makefile with color-coded output and comprehensive command organization
82
+ - Automated validation pipelines for publishing (build, test, lint, typecheck)
83
+ - Publishing scripts with safety checks and rollback procedures
84
+
85
+ ### Changed
86
+ - **Pull Command Behavior**: Breaking change in multi-customer environments (improvement)
87
+ - Previously: Required explicit customer selection or default customer configuration
88
+ - Now: Automatically pulls from all customers when no default is set
89
+ - Single customer setups: No change in behavior
90
+ - Multi-customer setups: Significantly improved user experience
91
+ - **Help Documentation**: Updated command descriptions and examples
92
+ - `newo pull` now shows "(all customers if no default)" in help text
93
+ - Enhanced multi-customer examples with auto-pull scenarios
94
+ - Updated usage patterns to reflect new workflow capabilities
95
+
96
+ ### Developer Experience
97
+ - **Publishing Automation**: One-command publishing to both GitHub and NPM with full validation
98
+ - **Comprehensive Testing**: Enhanced local testing documentation with step-by-step procedures
99
+ - **Professional Infrastructure**: Industry-standard publishing pipeline with version management
100
+ - **Quality Gates**: Automated validation before publishing (TypeScript, linting, building, package validation)
101
+
8
102
  ## [1.5.2] - 2025-01-15
9
103
 
10
104
  ### Enhanced
package/README.md CHANGED
@@ -25,7 +25,7 @@ Mirror NEWO "Project → Agent → Flow → Skills" structure to local files wit
25
25
 
26
26
  **Option 1: Global Installation (Recommended)**
27
27
  ```bash
28
- npm install -g newo
28
+ npm install -g newo@latest
29
29
  ```
30
30
 
31
31
  **Option 2: Local Project Installation**
package/dist/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type AxiosInstance } from 'axios';
2
- import type { ProjectMeta, Agent, Skill, FlowEvent, FlowState, AkbImportArticle, CustomerProfile } from './types.js';
2
+ import type { ProjectMeta, Agent, Skill, FlowEvent, FlowState, AkbImportArticle, CustomerProfile, CustomerAttribute, CustomerAttributesResponse } from './types.js';
3
3
  export declare function makeClient(verbose?: boolean, token?: string): Promise<AxiosInstance>;
4
4
  export declare function listProjects(client: AxiosInstance): Promise<ProjectMeta[]>;
5
5
  export declare function listAgents(client: AxiosInstance, projectId: string): Promise<Agent[]>;
@@ -11,4 +11,6 @@ export declare function listFlowEvents(client: AxiosInstance, flowId: string): P
11
11
  export declare function listFlowStates(client: AxiosInstance, flowId: string): Promise<FlowState[]>;
12
12
  export declare function importAkbArticle(client: AxiosInstance, articleData: AkbImportArticle): Promise<unknown>;
13
13
  export declare function getCustomerProfile(client: AxiosInstance): Promise<CustomerProfile>;
14
+ export declare function getCustomerAttributes(client: AxiosInstance, includeHidden?: boolean): Promise<CustomerAttributesResponse>;
15
+ export declare function updateCustomerAttribute(client: AxiosInstance, attribute: CustomerAttribute): Promise<void>;
14
16
  //# sourceMappingURL=api.d.ts.map
package/dist/api.js CHANGED
@@ -100,4 +100,25 @@ export async function getCustomerProfile(client) {
100
100
  const response = await client.get('/api/v1/customer/profile');
101
101
  return response.data;
102
102
  }
103
+ export async function getCustomerAttributes(client, includeHidden = true) {
104
+ const response = await client.get('/api/v1/bff/customer/attributes', {
105
+ params: { include_hidden: includeHidden }
106
+ });
107
+ return response.data;
108
+ }
109
+ export async function updateCustomerAttribute(client, attribute) {
110
+ if (!attribute.id) {
111
+ throw new Error(`Attribute ${attribute.idn} is missing ID - cannot update`);
112
+ }
113
+ await client.put(`/api/v1/customer/attributes/${attribute.id}`, {
114
+ idn: attribute.idn,
115
+ value: attribute.value,
116
+ title: attribute.title,
117
+ description: attribute.description,
118
+ group: attribute.group,
119
+ is_hidden: attribute.is_hidden,
120
+ possible_values: attribute.possible_values,
121
+ value_type: attribute.value_type
122
+ });
123
+ }
103
124
  //# sourceMappingURL=api.js.map
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import minimist from 'minimist';
3
3
  import dotenv from 'dotenv';
4
4
  import { makeClient, getProjectMeta, importAkbArticle } from './api.js';
5
- import { pullAll, pushChanged, status } from './sync.js';
5
+ import { pullAll, pushChanged, status, saveCustomerAttributes } from './sync.js';
6
6
  import { parseAkbFile, prepareArticlesForImport } from './akb.js';
7
7
  import { initializeEnvironment, ENV, EnvValidationError } from './env.js';
8
8
  import { parseCustomerConfigAsync, listCustomers, getCustomer, getDefaultCustomer, tryGetDefaultCustomer, getAllCustomers, validateCustomerConfig } from './customerAsync.js';
@@ -278,6 +278,11 @@ File Structure:
278
278
  const meta = await getProjectMeta(client, selectedCustomer.projectId);
279
279
  console.log(JSON.stringify(meta, null, 2));
280
280
  }
281
+ else if (cmd === 'pull-attributes') {
282
+ console.log(`🔍 Fetching customer attributes for ${selectedCustomer.idn}...`);
283
+ await saveCustomerAttributes(client, selectedCustomer, verbose);
284
+ console.log(`✅ Customer attributes saved to newo_customers/${selectedCustomer.idn}/attributes.yaml`);
285
+ }
281
286
  else if (cmd === 'import-akb') {
282
287
  const akbFile = args._[1];
283
288
  const personaId = args._[2];
package/dist/fsutil.d.ts CHANGED
@@ -9,7 +9,15 @@ export declare function hashesPath(customerIdn: string): string;
9
9
  export declare function ensureState(customerIdn: string): Promise<void>;
10
10
  export declare function projectDir(customerIdn: string, projectIdn: string): string;
11
11
  export declare function flowsYamlPath(customerIdn: string): string;
12
+ export declare function customerAttributesPath(customerIdn: string): string;
13
+ export declare function customerAttributesMapPath(customerIdn: string): string;
12
14
  export declare function skillPath(customerIdn: string, projectIdn: string, agentIdn: string, flowIdn: string, skillIdn: string, runnerType?: RunnerType): string;
15
+ export declare function skillFolderPath(customerIdn: string, projectIdn: string, agentIdn: string, flowIdn: string, skillIdn: string): string;
16
+ export declare function skillScriptPath(customerIdn: string, projectIdn: string, agentIdn: string, flowIdn: string, skillIdn: string, runnerType?: RunnerType): string;
17
+ export declare function projectMetadataPath(customerIdn: string, projectIdn: string): string;
18
+ export declare function agentMetadataPath(customerIdn: string, projectIdn: string, agentIdn: string): string;
19
+ export declare function flowMetadataPath(customerIdn: string, projectIdn: string, agentIdn: string, flowIdn: string): string;
20
+ export declare function skillMetadataPath(customerIdn: string, projectIdn: string, agentIdn: string, flowIdn: string, skillIdn: string): string;
13
21
  export declare function metadataPath(customerIdn: string, projectIdn: string): string;
14
22
  export declare const ROOT_DIR: string;
15
23
  export declare const MAP_PATH: string;
package/dist/fsutil.js CHANGED
@@ -28,10 +28,39 @@ export function projectDir(customerIdn, projectIdn) {
28
28
  export function flowsYamlPath(customerIdn) {
29
29
  return path.posix.join(customerProjectsDir(customerIdn), 'flows.yaml');
30
30
  }
31
+ export function customerAttributesPath(customerIdn) {
32
+ return path.posix.join(customerDir(customerIdn), 'attributes.yaml');
33
+ }
34
+ export function customerAttributesMapPath(customerIdn) {
35
+ return path.join(customerStateDir(customerIdn), 'attributes-map.json');
36
+ }
37
+ // Legacy skill path - direct file
31
38
  export function skillPath(customerIdn, projectIdn, agentIdn, flowIdn, skillIdn, runnerType = 'guidance') {
32
39
  const extension = runnerType === 'nsl' ? '.jinja' : '.guidance';
33
40
  return path.posix.join(customerProjectsDir(customerIdn), projectIdn, agentIdn, flowIdn, `${skillIdn}${extension}`);
34
41
  }
42
+ // New hierarchical structure paths
43
+ export function skillFolderPath(customerIdn, projectIdn, agentIdn, flowIdn, skillIdn) {
44
+ return path.posix.join(customerProjectsDir(customerIdn), projectIdn, agentIdn, flowIdn, skillIdn);
45
+ }
46
+ export function skillScriptPath(customerIdn, projectIdn, agentIdn, flowIdn, skillIdn, runnerType = 'guidance') {
47
+ const extension = runnerType === 'nsl' ? '.jinja' : '.guidance';
48
+ return path.posix.join(skillFolderPath(customerIdn, projectIdn, agentIdn, flowIdn, skillIdn), `skill${extension}`);
49
+ }
50
+ // Metadata paths for hierarchical structure
51
+ export function projectMetadataPath(customerIdn, projectIdn) {
52
+ return path.posix.join(customerProjectsDir(customerIdn), projectIdn, 'metadata.yaml');
53
+ }
54
+ export function agentMetadataPath(customerIdn, projectIdn, agentIdn) {
55
+ return path.posix.join(customerProjectsDir(customerIdn), projectIdn, agentIdn, 'metadata.yaml');
56
+ }
57
+ export function flowMetadataPath(customerIdn, projectIdn, agentIdn, flowIdn) {
58
+ return path.posix.join(customerProjectsDir(customerIdn), projectIdn, agentIdn, flowIdn, 'metadata.yaml');
59
+ }
60
+ export function skillMetadataPath(customerIdn, projectIdn, agentIdn, flowIdn, skillIdn) {
61
+ return path.posix.join(skillFolderPath(customerIdn, projectIdn, agentIdn, flowIdn, skillIdn), 'metadata.yaml');
62
+ }
63
+ // Legacy metadata path - keep for backwards compatibility
35
64
  export function metadataPath(customerIdn, projectIdn) {
36
65
  return path.posix.join(customerProjectsDir(customerIdn), projectIdn, 'metadata.json');
37
66
  }
package/dist/sync.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { AxiosInstance } from 'axios';
2
2
  import type { ProjectData, CustomerConfig } from './types.js';
3
+ export declare function saveCustomerAttributes(client: AxiosInstance, customer: CustomerConfig, verbose?: boolean): Promise<void>;
3
4
  export declare function pullSingleProject(client: AxiosInstance, customer: CustomerConfig, projectId: string, projectIdn: string, verbose?: boolean): Promise<ProjectData>;
4
5
  export declare function pullAll(client: AxiosInstance, customer: CustomerConfig, projectId?: string | null, verbose?: boolean): Promise<void>;
5
6
  export declare function pushChanged(client: AxiosInstance, customer: CustomerConfig, verbose?: boolean): Promise<void>;