newo 3.4.1 → 3.6.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/.env.example +5 -0
- package/CHANGELOG.md +31 -0
- package/dist/api.d.ts +18 -0
- package/dist/api.js +28 -0
- package/dist/cli/commands/create-attribute.js +1 -1
- package/dist/cli/commands/export.d.ts +3 -0
- package/dist/cli/commands/export.js +62 -0
- package/dist/cli/commands/help.js +54 -42
- package/dist/cli/commands/pull.js +38 -14
- package/dist/cli/commands/push.js +32 -32
- package/dist/cli/commands/status.js +46 -7
- package/dist/cli/commands/update-attribute.d.ts +3 -0
- package/dist/cli/commands/update-attribute.js +78 -0
- package/dist/cli-new/bootstrap.d.ts +7 -1
- package/dist/cli-new/bootstrap.js +11 -5
- package/dist/cli-new/di/tokens.d.ts +1 -0
- package/dist/cli-new/di/tokens.js +1 -0
- package/dist/cli.js +8 -0
- package/dist/domain/strategies/sync/ProjectSyncStrategy.d.ts +5 -0
- package/dist/domain/strategies/sync/ProjectSyncStrategy.js +97 -8
- package/dist/domain/strategies/sync/V2ProjectSyncStrategy.d.ts +80 -0
- package/dist/domain/strategies/sync/V2ProjectSyncStrategy.js +725 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.js +1 -0
- package/dist/format/detect.d.ts +14 -0
- package/dist/format/detect.js +105 -0
- package/dist/format/extensions.d.ts +26 -0
- package/dist/format/extensions.js +45 -0
- package/dist/format/index.d.ts +11 -0
- package/dist/format/index.js +11 -0
- package/dist/format/paths-v2.d.ts +31 -0
- package/dist/format/paths-v2.js +104 -0
- package/dist/format/types.d.ts +28 -0
- package/dist/format/types.js +21 -0
- package/dist/format/v2-yaml.d.ts +143 -0
- package/dist/format/v2-yaml.js +222 -0
- package/dist/format/yaml-patch.d.ts +14 -0
- package/dist/format/yaml-patch.js +184 -0
- package/dist/fsutil.d.ts +10 -0
- package/dist/fsutil.js +25 -0
- package/dist/sync/attributes.js +3 -3
- package/dist/sync/skill-files.js +2 -2
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/api.ts +64 -0
- package/src/cli/commands/create-attribute.ts +1 -1
- package/src/cli/commands/export.ts +78 -0
- package/src/cli/commands/help.ts +54 -42
- package/src/cli/commands/pull.ts +46 -15
- package/src/cli/commands/push.ts +38 -31
- package/src/cli/commands/status.ts +59 -9
- package/src/cli/commands/update-attribute.ts +82 -0
- package/src/cli-new/bootstrap.ts +19 -7
- package/src/cli-new/di/tokens.ts +1 -0
- package/src/cli.ts +10 -0
- package/src/domain/strategies/sync/ProjectSyncStrategy.ts +122 -8
- package/src/domain/strategies/sync/V2ProjectSyncStrategy.ts +1007 -0
- package/src/env.ts +2 -0
- package/src/format/detect.ts +123 -0
- package/src/format/extensions.ts +61 -0
- package/src/format/index.ts +66 -0
- package/src/format/paths-v2.ts +207 -0
- package/src/format/types.ts +40 -0
- package/src/format/v2-yaml.ts +345 -0
- package/src/format/yaml-patch.ts +208 -0
- package/src/fsutil.ts +37 -0
- package/src/sync/attributes.ts +3 -3
- package/src/sync/skill-files.ts +2 -2
- package/src/types.ts +6 -0
package/src/cli-new/bootstrap.ts
CHANGED
|
@@ -11,6 +11,8 @@ import { ConsoleLogger, type ILogger, type CustomerConfig, type MultiCustomerCon
|
|
|
11
11
|
import { SyncEngine, type SyncEngineOptions } from '../application/sync/SyncEngine.js';
|
|
12
12
|
import { MigrationEngine, TransformService } from '../application/migration/MigrationEngine.js';
|
|
13
13
|
import { ProjectSyncStrategy, createProjectSyncStrategy } from '../domain/strategies/sync/ProjectSyncStrategy.js';
|
|
14
|
+
import { createV2ProjectSyncStrategy } from '../domain/strategies/sync/V2ProjectSyncStrategy.js';
|
|
15
|
+
import type { FormatVersion } from '../format/types.js';
|
|
14
16
|
import { AttributeSyncStrategy, createAttributeSyncStrategy } from '../domain/strategies/sync/AttributeSyncStrategy.js';
|
|
15
17
|
import { IntegrationSyncStrategy, createIntegrationSyncStrategy } from '../domain/strategies/sync/IntegrationSyncStrategy.js';
|
|
16
18
|
import { AkbSyncStrategy, createAkbSyncStrategy } from '../domain/strategies/sync/AkbSyncStrategy.js';
|
|
@@ -30,7 +32,7 @@ export async function createApiClient(customer: CustomerConfig, verbose: boolean
|
|
|
30
32
|
process.env.NEWO_PROJECT_ID = customer.projectId;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
const token = await getValidAccessToken();
|
|
35
|
+
const token = await getValidAccessToken(customer);
|
|
34
36
|
return makeClient(verbose, token);
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -47,6 +49,12 @@ export interface BootstrapOptions {
|
|
|
47
49
|
* Sync engine options
|
|
48
50
|
*/
|
|
49
51
|
syncEngineOptions?: SyncEngineOptions;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Format version for project sync strategy
|
|
55
|
+
* 'newo_v2' uses V2ProjectSyncStrategy, 'cli_v1' (default) uses ProjectSyncStrategy
|
|
56
|
+
*/
|
|
57
|
+
formatVersion?: FormatVersion | undefined;
|
|
50
58
|
}
|
|
51
59
|
|
|
52
60
|
/**
|
|
@@ -73,10 +81,13 @@ export function createServiceContainer(
|
|
|
73
81
|
|
|
74
82
|
// === Domain Layer - Sync Strategies ===
|
|
75
83
|
|
|
76
|
-
// Project Sync Strategy
|
|
77
|
-
container.registerSingleton(TOKENS.PROJECT_SYNC_STRATEGY, () =>
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
// Project Sync Strategy (format-conditional: cli_v1 or newo_v2)
|
|
85
|
+
container.registerSingleton(TOKENS.PROJECT_SYNC_STRATEGY, () => {
|
|
86
|
+
if (options.formatVersion === 'newo_v2') {
|
|
87
|
+
return createV2ProjectSyncStrategy(createApiClient, container.get<ILogger>(TOKENS.LOGGER));
|
|
88
|
+
}
|
|
89
|
+
return createProjectSyncStrategy(createApiClient, container.get<ILogger>(TOKENS.LOGGER));
|
|
90
|
+
});
|
|
80
91
|
|
|
81
92
|
// Attribute Sync Strategy
|
|
82
93
|
container.registerSingleton(TOKENS.ATTRIBUTE_SYNC_STRATEGY, () =>
|
|
@@ -151,14 +162,15 @@ export function getLogger(container: ServiceContainer): ILogger {
|
|
|
151
162
|
*/
|
|
152
163
|
export function setupCli(
|
|
153
164
|
customerConfig: MultiCustomerConfig,
|
|
154
|
-
verbose: boolean = false
|
|
165
|
+
verbose: boolean = false,
|
|
166
|
+
formatVersion?: FormatVersion
|
|
155
167
|
): {
|
|
156
168
|
container: ServiceContainer;
|
|
157
169
|
syncEngine: SyncEngine;
|
|
158
170
|
migrationEngine: MigrationEngine;
|
|
159
171
|
logger: ILogger;
|
|
160
172
|
} {
|
|
161
|
-
const container = createServiceContainer(customerConfig, { verbose });
|
|
173
|
+
const container = createServiceContainer(customerConfig, { verbose, formatVersion });
|
|
162
174
|
|
|
163
175
|
return {
|
|
164
176
|
container,
|
package/src/cli-new/di/tokens.ts
CHANGED
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';
|
|
@@ -45,6 +46,7 @@ import { handleAddProjectCommand } from './cli/commands/add-project.js';
|
|
|
45
46
|
import { handleWatchCommand } from './cli/commands/watch.js';
|
|
46
47
|
import { handleDiffCommand } from './cli/commands/diff.js';
|
|
47
48
|
import { handleLogsCommand } from './cli/commands/logs.js';
|
|
49
|
+
import { handleExportCommand } from './cli/commands/export.js';
|
|
48
50
|
import type { CliArgs, NewoApiError } from './types.js';
|
|
49
51
|
|
|
50
52
|
dotenv.config();
|
|
@@ -110,6 +112,10 @@ async function main(): Promise<void> {
|
|
|
110
112
|
await handleLogsCommand(customerConfig, args, verbose);
|
|
111
113
|
break;
|
|
112
114
|
|
|
115
|
+
case 'export':
|
|
116
|
+
await handleExportCommand(customerConfig, args, verbose);
|
|
117
|
+
break;
|
|
118
|
+
|
|
113
119
|
case 'conversations':
|
|
114
120
|
await handleConversationsCommand(customerConfig, args, verbose);
|
|
115
121
|
break;
|
|
@@ -182,6 +188,10 @@ async function main(): Promise<void> {
|
|
|
182
188
|
await handleCreateAttributeCommand(customerConfig, args, verbose);
|
|
183
189
|
break;
|
|
184
190
|
|
|
191
|
+
case 'update-attribute':
|
|
192
|
+
await handleUpdateAttributeCommand(customerConfig, args, verbose);
|
|
193
|
+
break;
|
|
194
|
+
|
|
185
195
|
case 'pull-integrations':
|
|
186
196
|
await handlePullIntegrationsCommand(customerConfig, args, verbose);
|
|
187
197
|
break;
|
|
@@ -46,7 +46,9 @@ import {
|
|
|
46
46
|
listFlowEvents,
|
|
47
47
|
listFlowStates,
|
|
48
48
|
updateSkill,
|
|
49
|
-
publishFlow
|
|
49
|
+
publishFlow,
|
|
50
|
+
listLibraries,
|
|
51
|
+
updateLibrarySkill,
|
|
50
52
|
} from '../../../api.js';
|
|
51
53
|
import {
|
|
52
54
|
ensureState,
|
|
@@ -60,7 +62,10 @@ import {
|
|
|
60
62
|
skillFolderPath,
|
|
61
63
|
flowsYamlPath,
|
|
62
64
|
customerProjectsDir,
|
|
63
|
-
projectDir
|
|
65
|
+
projectDir,
|
|
66
|
+
libraryMetadataPath,
|
|
67
|
+
librarySkillMetadataPath,
|
|
68
|
+
librarySkillScriptPath,
|
|
64
69
|
} from '../../../fsutil.js';
|
|
65
70
|
import { sha256, saveHashes, loadHashes } from '../../../hash.js';
|
|
66
71
|
import { generateFlowsYaml } from '../../../sync/metadata.js';
|
|
@@ -241,6 +246,52 @@ export class ProjectSyncStrategy implements ISyncStrategy<ProjectMeta, LocalProj
|
|
|
241
246
|
}
|
|
242
247
|
}
|
|
243
248
|
|
|
249
|
+
// Pull libraries for this project
|
|
250
|
+
try {
|
|
251
|
+
const libraries = await listLibraries(client, project.id);
|
|
252
|
+
if (libraries.length > 0) {
|
|
253
|
+
this.logger.verbose(` Found ${libraries.length} libraries in project ${project.idn}`);
|
|
254
|
+
projectData.libraries = {};
|
|
255
|
+
|
|
256
|
+
for (const lib of libraries) {
|
|
257
|
+
projectData.libraries[lib.idn] = {
|
|
258
|
+
id: lib.id,
|
|
259
|
+
skills: {}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Save library metadata
|
|
263
|
+
const libMetaPath = libraryMetadataPath(customer.idn, project.idn, lib.idn);
|
|
264
|
+
const libMeta = { id: lib.id, idn: lib.idn };
|
|
265
|
+
const libMetaYaml = yaml.dump(libMeta, { indent: 2, quotingType: '"', forceQuotes: false });
|
|
266
|
+
await writeFileSafe(libMetaPath, libMetaYaml);
|
|
267
|
+
hashes[libMetaPath] = sha256(libMetaYaml);
|
|
268
|
+
|
|
269
|
+
for (const skill of lib.skills) {
|
|
270
|
+
// Save skill metadata
|
|
271
|
+
const skillMetaPath = librarySkillMetadataPath(customer.idn, project.idn, lib.idn, skill.idn);
|
|
272
|
+
const skillMeta: SkillMetadata = {
|
|
273
|
+
id: skill.id, idn: skill.idn, title: skill.title,
|
|
274
|
+
runner_type: skill.runner_type, model: skill.model,
|
|
275
|
+
parameters: [...skill.parameters], path: skill.path
|
|
276
|
+
};
|
|
277
|
+
const skillMetaYaml = yaml.dump(skillMeta, { indent: 2, quotingType: '"', forceQuotes: false });
|
|
278
|
+
await writeFileSafe(skillMetaPath, skillMetaYaml);
|
|
279
|
+
hashes[skillMetaPath] = sha256(skillMetaYaml);
|
|
280
|
+
|
|
281
|
+
// Save skill script
|
|
282
|
+
const scriptContent = skill.prompt_script || '';
|
|
283
|
+
const scriptPath = librarySkillScriptPath(customer.idn, project.idn, lib.idn, skill.idn, skill.runner_type);
|
|
284
|
+
await writeFileSafe(scriptPath, scriptContent);
|
|
285
|
+
hashes[scriptPath] = sha256(scriptContent);
|
|
286
|
+
|
|
287
|
+
projectData.libraries[lib.idn]!.skills[skill.idn] = skillMeta;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
} catch (error) {
|
|
292
|
+
this.logger.verbose(` Could not pull libraries for project ${project.idn}: ${error instanceof Error ? error.message : String(error)}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
244
295
|
existingMap.projects[project.idn] = projectData;
|
|
245
296
|
projects.push(localProject);
|
|
246
297
|
}
|
|
@@ -489,11 +540,15 @@ export class ProjectSyncStrategy implements ISyncStrategy<ProjectMeta, LocalProj
|
|
|
489
540
|
for (const change of changes) {
|
|
490
541
|
try {
|
|
491
542
|
if (change.operation === 'modified') {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
543
|
+
const isLibrary = change.path.includes('/libraries/');
|
|
544
|
+
if (isLibrary) {
|
|
545
|
+
const updateResult = await this.pushLibrarySkillUpdate(client, change, mapData, newHashes);
|
|
546
|
+
result.updated += updateResult;
|
|
547
|
+
} else {
|
|
548
|
+
const updateResult = await this.pushSkillUpdate(client, customer, change, mapData, newHashes);
|
|
549
|
+
result.updated += updateResult;
|
|
550
|
+
}
|
|
495
551
|
} else if (change.operation === 'created') {
|
|
496
|
-
// Create new entity
|
|
497
552
|
const createResult = await this.pushNewEntity(client, customer, change, mapData, newHashes);
|
|
498
553
|
result.created += createResult;
|
|
499
554
|
}
|
|
@@ -563,6 +618,40 @@ export class ProjectSyncStrategy implements ISyncStrategy<ProjectMeta, LocalProj
|
|
|
563
618
|
return 1;
|
|
564
619
|
}
|
|
565
620
|
|
|
621
|
+
/**
|
|
622
|
+
* Push a library skill update
|
|
623
|
+
* Path: newo_customers/{customer}/projects/{project}/libraries/{lib}/{skill}/{skill}.jinja
|
|
624
|
+
*/
|
|
625
|
+
private async pushLibrarySkillUpdate(
|
|
626
|
+
client: AxiosInstance,
|
|
627
|
+
change: ChangeItem<LocalProjectData>,
|
|
628
|
+
mapData: ProjectMap,
|
|
629
|
+
newHashes: HashStore
|
|
630
|
+
): Promise<number> {
|
|
631
|
+
const pathParts = change.path.split('/');
|
|
632
|
+
const skillIdn = pathParts[pathParts.length - 2] || '';
|
|
633
|
+
const libIdn = pathParts[pathParts.length - 3] || '';
|
|
634
|
+
const projectIdn = pathParts[pathParts.length - 5] || '';
|
|
635
|
+
|
|
636
|
+
const projectData = mapData.projects[projectIdn];
|
|
637
|
+
const libData = projectData?.libraries?.[libIdn];
|
|
638
|
+
const skillData = libData?.skills[skillIdn];
|
|
639
|
+
|
|
640
|
+
if (!skillData || !libData) {
|
|
641
|
+
throw new Error(`Library skill ${skillIdn} not found in project map`);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
const content = await fs.readFile(change.path, 'utf8');
|
|
645
|
+
|
|
646
|
+
await updateLibrarySkill(client, libData.id, skillData.id, {
|
|
647
|
+
prompt_script: content,
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
newHashes[change.path] = sha256(content);
|
|
651
|
+
this.logger.info(`Pushed library skill: ${libIdn}/${skillIdn}`);
|
|
652
|
+
return 1;
|
|
653
|
+
}
|
|
654
|
+
|
|
566
655
|
/**
|
|
567
656
|
* Push a new entity
|
|
568
657
|
*/
|
|
@@ -616,7 +705,7 @@ export class ProjectSyncStrategy implements ISyncStrategy<ProjectMeta, LocalProj
|
|
|
616
705
|
const hashes = await loadHashes(customer.idn);
|
|
617
706
|
const mapData = await fs.readJson(mapFile) as ProjectMap;
|
|
618
707
|
|
|
619
|
-
// Scan for changed skill scripts
|
|
708
|
+
// Scan for changed flow skill scripts
|
|
620
709
|
for (const [projectIdn, projectData] of Object.entries(mapData.projects)) {
|
|
621
710
|
for (const [agentIdn, agentData] of Object.entries(projectData.agents)) {
|
|
622
711
|
for (const [flowIdn, flowData] of Object.entries(agentData.flows)) {
|
|
@@ -629,7 +718,7 @@ export class ProjectSyncStrategy implements ISyncStrategy<ProjectMeta, LocalProj
|
|
|
629
718
|
|
|
630
719
|
if (storedHash !== currentHash) {
|
|
631
720
|
changes.push({
|
|
632
|
-
item: {} as LocalProjectData,
|
|
721
|
+
item: {} as LocalProjectData,
|
|
633
722
|
operation: 'modified',
|
|
634
723
|
path: skillFile.filePath
|
|
635
724
|
});
|
|
@@ -638,6 +727,31 @@ export class ProjectSyncStrategy implements ISyncStrategy<ProjectMeta, LocalProj
|
|
|
638
727
|
}
|
|
639
728
|
}
|
|
640
729
|
}
|
|
730
|
+
|
|
731
|
+
// Scan for changed library skill scripts
|
|
732
|
+
if (projectData.libraries) {
|
|
733
|
+
for (const [libIdn, libData] of Object.entries(projectData.libraries)) {
|
|
734
|
+
for (const [skillIdn, skillMeta] of Object.entries(libData.skills)) {
|
|
735
|
+
const scriptPath = librarySkillScriptPath(
|
|
736
|
+
customer.idn, projectIdn, libIdn, skillIdn, skillMeta.runner_type
|
|
737
|
+
);
|
|
738
|
+
|
|
739
|
+
if (await fs.pathExists(scriptPath)) {
|
|
740
|
+
const content = await fs.readFile(scriptPath, 'utf8');
|
|
741
|
+
const currentHash = sha256(content);
|
|
742
|
+
const storedHash = hashes[scriptPath];
|
|
743
|
+
|
|
744
|
+
if (storedHash !== currentHash) {
|
|
745
|
+
changes.push({
|
|
746
|
+
item: {} as LocalProjectData,
|
|
747
|
+
operation: 'modified',
|
|
748
|
+
path: scriptPath
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
641
755
|
}
|
|
642
756
|
|
|
643
757
|
return changes;
|