newo 3.4.1 → 3.4.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,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.4.2] - 2026-04-12
11
+
12
+ ### Added
13
+
14
+ - **`newo update-attribute` command**: Update existing customer attributes by IDN. Supports `--value`, `--title`, `--description`, `--group`, `--hidden`, `--value-type`, and `--possible-values` flags. Only explicitly provided fields are overridden; unspecified fields retain their current values.
15
+
16
+ ### Fixed
17
+
18
+ - **`create-attribute --value 0`**: Fixed a bug where numeric zero values passed via `--value 0` were incorrectly rejected as "value required". The minimist argument parser returns numeric `0` which was treated as falsy by the `||` operator. Now uses explicit `undefined` check.
19
+
10
20
  ## [3.4.1] - 2026-04-12
11
21
 
12
22
  ### Fixed
@@ -9,7 +9,7 @@ export async function handleCreateAttributeCommand(customerConfig, args, verbose
9
9
  const selectedCustomer = requireSingleCustomer(customerConfig, args.customer);
10
10
  // Parse arguments
11
11
  const idn = args._[1];
12
- const value = args.value || '';
12
+ const value = args.value !== undefined ? String(args.value) : '';
13
13
  const title = args.title || idn;
14
14
  const description = args.description || '';
15
15
  const group = args.group || 'General';
@@ -0,0 +1,3 @@
1
+ import type { MultiCustomerConfig, CliArgs } from '../../types.js';
2
+ export declare function handleUpdateAttributeCommand(customerConfig: MultiCustomerConfig, args: CliArgs, verbose?: boolean): Promise<void>;
3
+ //# sourceMappingURL=update-attribute.d.ts.map
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Update Customer Attribute Command Handler
3
+ */
4
+ import { makeClient, getCustomerAttributes, updateCustomerAttribute } from '../../api.js';
5
+ import { getValidAccessToken } from '../../auth.js';
6
+ import { requireSingleCustomer } from '../customer-selection.js';
7
+ export async function handleUpdateAttributeCommand(customerConfig, args, verbose = false) {
8
+ try {
9
+ const selectedCustomer = requireSingleCustomer(customerConfig, args.customer);
10
+ // Parse arguments
11
+ const idn = args._[1];
12
+ if (!idn) {
13
+ console.error('Error: Attribute IDN is required');
14
+ console.error('Usage: newo update-attribute <idn> [--value <value>] [--title <title>] [--description <desc>] [--group <group>] [--hidden] [--value-type <type>] [--possible-values <val1,val2>]');
15
+ process.exit(1);
16
+ }
17
+ // Get access token and create client
18
+ const accessToken = await getValidAccessToken(selectedCustomer);
19
+ const client = await makeClient(verbose, accessToken);
20
+ // Fetch existing attributes to find the one to update
21
+ const response = await getCustomerAttributes(client, true);
22
+ const existing = response.attributes.find((a) => a.idn === idn);
23
+ if (!existing) {
24
+ console.error(`❌ Attribute '${idn}' not found. Use 'newo create-attribute' to create it.`);
25
+ process.exit(1);
26
+ }
27
+ if (!existing.id) {
28
+ console.error(`❌ Attribute '${idn}' has no ID. Cannot update.`);
29
+ process.exit(1);
30
+ }
31
+ // Build updated attribute - only override fields that were explicitly provided
32
+ const updated = {
33
+ id: existing.id,
34
+ idn: existing.idn,
35
+ value: args.value !== undefined ? String(args.value) : existing.value,
36
+ title: args.title || existing.title,
37
+ description: args.description || existing.description,
38
+ group: args.group || existing.group,
39
+ is_hidden: args.hidden !== undefined ? Boolean(args.hidden) : existing.is_hidden,
40
+ possible_values: args['possible-values']
41
+ ? args['possible-values'].split(',').map(v => v.trim())
42
+ : existing.possible_values,
43
+ value_type: args['value-type'] || existing.value_type
44
+ };
45
+ if (verbose) {
46
+ console.log(`📝 Updating customer attribute: ${idn} (ID: ${existing.id})`);
47
+ if (args.value !== undefined)
48
+ console.log(` Value: ${existing.value} -> ${updated.value}`);
49
+ if (args.title)
50
+ console.log(` Title: ${existing.title} -> ${updated.title}`);
51
+ if (args.description)
52
+ console.log(` Description: updated`);
53
+ if (args.group)
54
+ console.log(` Group: ${existing.group} -> ${updated.group}`);
55
+ if (args['value-type'])
56
+ console.log(` Type: ${existing.value_type} -> ${updated.value_type}`);
57
+ if (args.hidden !== undefined)
58
+ console.log(` Hidden: ${existing.is_hidden} -> ${updated.is_hidden}`);
59
+ }
60
+ await updateCustomerAttribute(client, updated);
61
+ console.log(`✅ Customer attribute updated: ${idn}`);
62
+ if (args.value !== undefined)
63
+ console.log(` Value: ${updated.value}`);
64
+ if (args['value-type'])
65
+ console.log(` Type: ${updated.value_type}`);
66
+ if (args.title)
67
+ console.log(` Title: ${updated.title}`);
68
+ if (args.description)
69
+ console.log(` Description: updated`);
70
+ if (args.group)
71
+ console.log(` Group: ${updated.group}`);
72
+ }
73
+ catch (error) {
74
+ console.error('❌ Failed to update customer attribute:', error instanceof Error ? error.message : String(error));
75
+ process.exit(1);
76
+ }
77
+ }
78
+ //# sourceMappingURL=update-attribute.js.map
package/dist/cli.js CHANGED
@@ -29,6 +29,7 @@ import { handleCreateStateCommand } from './cli/commands/create-state.js';
29
29
  import { handleCreateParameterCommand } from './cli/commands/create-parameter.js';
30
30
  import { handleCreatePersonaCommand } from './cli/commands/create-persona.js';
31
31
  import { handleCreateAttributeCommand } from './cli/commands/create-attribute.js';
32
+ import { handleUpdateAttributeCommand } from './cli/commands/update-attribute.js';
32
33
  import { handleSandboxCommand } from './cli/commands/sandbox.js';
33
34
  import { handlePullIntegrationsCommand } from './cli/commands/pull-integrations.js';
34
35
  import { handlePushIntegrationsCommand } from './cli/commands/push-integrations.js';
@@ -153,6 +154,9 @@ async function main() {
153
154
  case 'create-attribute':
154
155
  await handleCreateAttributeCommand(customerConfig, args, verbose);
155
156
  break;
157
+ case 'update-attribute':
158
+ await handleUpdateAttributeCommand(customerConfig, args, verbose);
159
+ break;
156
160
  case 'pull-integrations':
157
161
  await handlePullIntegrationsCommand(customerConfig, args, verbose);
158
162
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newo",
3
- "version": "3.4.1",
3
+ "version": "3.4.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": {
@@ -16,7 +16,7 @@ export async function handleCreateAttributeCommand(
16
16
 
17
17
  // Parse arguments
18
18
  const idn = args._[1] as string;
19
- const value = args.value as string || '';
19
+ const value = args.value !== undefined ? String(args.value) : '';
20
20
  const title = args.title as string || idn;
21
21
  const description = args.description as string || '';
22
22
  const group = args.group as string || 'General';
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Update Customer Attribute Command Handler
3
+ */
4
+ import { makeClient, getCustomerAttributes, updateCustomerAttribute } from '../../api.js';
5
+ import { getValidAccessToken } from '../../auth.js';
6
+ import { requireSingleCustomer } from '../customer-selection.js';
7
+ import type { MultiCustomerConfig, CliArgs, CustomerAttribute } from '../../types.js';
8
+
9
+ export async function handleUpdateAttributeCommand(
10
+ customerConfig: MultiCustomerConfig,
11
+ args: CliArgs,
12
+ verbose: boolean = false
13
+ ): Promise<void> {
14
+ try {
15
+ const selectedCustomer = requireSingleCustomer(customerConfig, args.customer as string | undefined);
16
+
17
+ // Parse arguments
18
+ const idn = args._[1] as string;
19
+
20
+ if (!idn) {
21
+ console.error('Error: Attribute IDN is required');
22
+ console.error('Usage: newo update-attribute <idn> [--value <value>] [--title <title>] [--description <desc>] [--group <group>] [--hidden] [--value-type <type>] [--possible-values <val1,val2>]');
23
+ process.exit(1);
24
+ }
25
+
26
+ // Get access token and create client
27
+ const accessToken = await getValidAccessToken(selectedCustomer);
28
+ const client = await makeClient(verbose, accessToken);
29
+
30
+ // Fetch existing attributes to find the one to update
31
+ const response = await getCustomerAttributes(client, true);
32
+ const existing = response.attributes.find((a: CustomerAttribute) => a.idn === idn);
33
+
34
+ if (!existing) {
35
+ console.error(`❌ Attribute '${idn}' not found. Use 'newo create-attribute' to create it.`);
36
+ process.exit(1);
37
+ }
38
+
39
+ if (!existing.id) {
40
+ console.error(`❌ Attribute '${idn}' has no ID. Cannot update.`);
41
+ process.exit(1);
42
+ }
43
+
44
+ // Build updated attribute - only override fields that were explicitly provided
45
+ const updated: CustomerAttribute = {
46
+ id: existing.id,
47
+ idn: existing.idn,
48
+ value: args.value !== undefined ? String(args.value) : existing.value,
49
+ title: (args.title as string) || existing.title,
50
+ description: (args.description as string) || existing.description,
51
+ group: (args.group as string) || existing.group,
52
+ is_hidden: args.hidden !== undefined ? Boolean(args.hidden) : existing.is_hidden,
53
+ possible_values: args['possible-values']
54
+ ? (args['possible-values'] as string).split(',').map(v => v.trim())
55
+ : existing.possible_values,
56
+ value_type: (args['value-type'] as string) || existing.value_type
57
+ };
58
+
59
+ if (verbose) {
60
+ console.log(`📝 Updating customer attribute: ${idn} (ID: ${existing.id})`);
61
+ if (args.value !== undefined) console.log(` Value: ${existing.value} -> ${updated.value}`);
62
+ if (args.title) console.log(` Title: ${existing.title} -> ${updated.title}`);
63
+ if (args.description) console.log(` Description: updated`);
64
+ if (args.group) console.log(` Group: ${existing.group} -> ${updated.group}`);
65
+ if (args['value-type']) console.log(` Type: ${existing.value_type} -> ${updated.value_type}`);
66
+ if (args.hidden !== undefined) console.log(` Hidden: ${existing.is_hidden} -> ${updated.is_hidden}`);
67
+ }
68
+
69
+ await updateCustomerAttribute(client, updated);
70
+
71
+ console.log(`✅ Customer attribute updated: ${idn}`);
72
+ if (args.value !== undefined) console.log(` Value: ${updated.value}`);
73
+ if (args['value-type']) console.log(` Type: ${updated.value_type}`);
74
+ if (args.title) console.log(` Title: ${updated.title}`);
75
+ if (args.description) console.log(` Description: updated`);
76
+ if (args.group) console.log(` Group: ${updated.group}`);
77
+
78
+ } catch (error: unknown) {
79
+ console.error('❌ Failed to update customer attribute:', error instanceof Error ? error.message : String(error));
80
+ process.exit(1);
81
+ }
82
+ }
package/src/cli.ts CHANGED
@@ -29,6 +29,7 @@ import { handleCreateStateCommand } from './cli/commands/create-state.js';
29
29
  import { handleCreateParameterCommand } from './cli/commands/create-parameter.js';
30
30
  import { handleCreatePersonaCommand } from './cli/commands/create-persona.js';
31
31
  import { handleCreateAttributeCommand } from './cli/commands/create-attribute.js';
32
+ import { handleUpdateAttributeCommand } from './cli/commands/update-attribute.js';
32
33
  import { handleSandboxCommand } from './cli/commands/sandbox.js';
33
34
  import { handlePullIntegrationsCommand } from './cli/commands/pull-integrations.js';
34
35
  import { handlePushIntegrationsCommand } from './cli/commands/push-integrations.js';
@@ -182,6 +183,10 @@ async function main(): Promise<void> {
182
183
  await handleCreateAttributeCommand(customerConfig, args, verbose);
183
184
  break;
184
185
 
186
+ case 'update-attribute':
187
+ await handleUpdateAttributeCommand(customerConfig, args, verbose);
188
+ break;
189
+
185
190
  case 'pull-integrations':
186
191
  await handlePullIntegrationsCommand(customerConfig, args, verbose);
187
192
  break;