@agentuity/migrate 3.0.0-alpha.0 → 3.0.0-alpha.1
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/bin/migrate.ts +93 -10
- package/dist/detect-v3.d.ts +92 -0
- package/dist/detect-v3.d.ts.map +1 -0
- package/dist/detect-v3.js +675 -0
- package/dist/detect-v3.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/migrate-v3.d.ts +38 -0
- package/dist/migrate-v3.d.ts.map +1 -0
- package/dist/migrate-v3.js +448 -0
- package/dist/migrate-v3.js.map +1 -0
- package/dist/report.d.ts +3 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +64 -0
- package/dist/report.js.map +1 -1
- package/dist/transforms/v3/agents.d.ts +33 -0
- package/dist/transforms/v3/agents.d.ts.map +1 -0
- package/dist/transforms/v3/agents.js +335 -0
- package/dist/transforms/v3/agents.js.map +1 -0
- package/dist/transforms/v3/dev-setup.d.ts +27 -0
- package/dist/transforms/v3/dev-setup.d.ts.map +1 -0
- package/dist/transforms/v3/dev-setup.js +103 -0
- package/dist/transforms/v3/dev-setup.js.map +1 -0
- package/dist/transforms/v3/entry-point.d.ts +23 -0
- package/dist/transforms/v3/entry-point.d.ts.map +1 -0
- package/dist/transforms/v3/entry-point.js +67 -0
- package/dist/transforms/v3/entry-point.js.map +1 -0
- package/dist/transforms/v3/package-json.d.ts +28 -0
- package/dist/transforms/v3/package-json.d.ts.map +1 -0
- package/dist/transforms/v3/package-json.js +151 -0
- package/dist/transforms/v3/package-json.js.map +1 -0
- package/dist/transforms/v3/routes.d.ts +37 -0
- package/dist/transforms/v3/routes.d.ts.map +1 -0
- package/dist/transforms/v3/routes.js +146 -0
- package/dist/transforms/v3/routes.js.map +1 -0
- package/dist/transforms/v3/services.d.ts +19 -0
- package/dist/transforms/v3/services.d.ts.map +1 -0
- package/dist/transforms/v3/services.js +61 -0
- package/dist/transforms/v3/services.js.map +1 -0
- package/package.json +4 -4
- package/src/detect-v3.ts +867 -0
- package/src/index.ts +13 -0
- package/src/migrate-v3.ts +539 -0
- package/src/report.ts +86 -0
- package/src/transforms/v3/agents.ts +434 -0
- package/src/transforms/v3/dev-setup.ts +137 -0
- package/src/transforms/v3/entry-point.ts +90 -0
- package/src/transforms/v3/package-json.ts +183 -0
- package/src/transforms/v3/routes.ts +185 -0
- package/src/transforms/v3/services.ts +76 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform: package.json for v2 → v3 migration.
|
|
3
|
+
*
|
|
4
|
+
* - Removes @agentuity/runtime
|
|
5
|
+
* - Adds hono and @agentuity/hono
|
|
6
|
+
* - Adds individual service packages based on detected usage
|
|
7
|
+
* - Bumps all @agentuity/* packages to ^3.0.0
|
|
8
|
+
* - Updates start script if it references old entry point
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { SERVICE_PACKAGE_MAP, type V3OutdatedPackage } from '../../detect-v3';
|
|
12
|
+
|
|
13
|
+
export interface V3PackageJsonResult {
|
|
14
|
+
/** Transformed package.json content, or null if no changes */
|
|
15
|
+
content: string | null;
|
|
16
|
+
/** Description of each change */
|
|
17
|
+
changes: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Transform package.json for v3 migration.
|
|
22
|
+
*/
|
|
23
|
+
export function transformPackageJsonV3(
|
|
24
|
+
source: string,
|
|
25
|
+
outdatedPackages: V3OutdatedPackage[],
|
|
26
|
+
servicesUsed: string[],
|
|
27
|
+
options?: {
|
|
28
|
+
/** Whether the project had @agentuity/runtime */
|
|
29
|
+
removeRuntime?: boolean;
|
|
30
|
+
/** Whether to remove @agentuity/react */
|
|
31
|
+
removeReact?: boolean;
|
|
32
|
+
/** Dev scripts to add (from dev-setup transform) */
|
|
33
|
+
devScripts?: Record<string, string>;
|
|
34
|
+
}
|
|
35
|
+
): V3PackageJsonResult {
|
|
36
|
+
const changes: string[] = [];
|
|
37
|
+
let pkg: Record<string, unknown>;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
pkg = JSON.parse(source);
|
|
41
|
+
} catch {
|
|
42
|
+
return { content: null, changes: ['Failed to parse package.json'] };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const deps = (pkg.dependencies ?? {}) as Record<string, string>;
|
|
46
|
+
const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;
|
|
47
|
+
|
|
48
|
+
// ── 1. Remove @agentuity/runtime ──────────────────────────────────────
|
|
49
|
+
if (options?.removeRuntime && deps['@agentuity/runtime']) {
|
|
50
|
+
delete deps['@agentuity/runtime'];
|
|
51
|
+
changes.push('Removed @agentuity/runtime from dependencies');
|
|
52
|
+
}
|
|
53
|
+
if (options?.removeRuntime && devDeps['@agentuity/runtime']) {
|
|
54
|
+
delete devDeps['@agentuity/runtime'];
|
|
55
|
+
changes.push('Removed @agentuity/runtime from devDependencies');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── 2. Add hono ───────────────────────────────────────────────────────
|
|
59
|
+
if (!deps['hono']) {
|
|
60
|
+
deps['hono'] = '^4.0.0';
|
|
61
|
+
changes.push('Added hono@^4.0.0 to dependencies');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ── 3. Add @agentuity/hono ────────────────────────────────────────────
|
|
65
|
+
if (!deps['@agentuity/hono']) {
|
|
66
|
+
deps['@agentuity/hono'] = '^3.0.0';
|
|
67
|
+
changes.push('Added @agentuity/hono@^3.0.0 to dependencies');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ── 4. Add individual service packages based on usage ─────────────────
|
|
71
|
+
for (const service of servicesUsed) {
|
|
72
|
+
if (service === 'logger') {
|
|
73
|
+
// Logger comes from telemetry
|
|
74
|
+
if (!deps['@agentuity/telemetry']) {
|
|
75
|
+
deps['@agentuity/telemetry'] = '^3.0.0';
|
|
76
|
+
changes.push('Added @agentuity/telemetry@^3.0.0 (for logger)');
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const mapping = SERVICE_PACKAGE_MAP[service];
|
|
82
|
+
if (!mapping) continue;
|
|
83
|
+
|
|
84
|
+
if (!deps[mapping.pkg]) {
|
|
85
|
+
deps[mapping.pkg] = '^3.0.0';
|
|
86
|
+
changes.push(`Added ${mapping.pkg}@^3.0.0 (${service} service detected in use)`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── 5. Bump existing @agentuity/* packages to ^3.0.0 ──────────────────
|
|
91
|
+
for (const outdated of outdatedPackages) {
|
|
92
|
+
const section = outdated.section === 'dependencies' ? deps : devDeps;
|
|
93
|
+
if (section[outdated.name]) {
|
|
94
|
+
section[outdated.name] = '^3.0.0';
|
|
95
|
+
changes.push(`Updated ${outdated.name} ${outdated.currentVersion} → ^3.0.0`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ── 6. Remove @agentuity/react if requested ───────────────────────────
|
|
100
|
+
if (options?.removeReact) {
|
|
101
|
+
if (deps['@agentuity/react']) {
|
|
102
|
+
delete deps['@agentuity/react'];
|
|
103
|
+
changes.push('Removed @agentuity/react from dependencies (deprecated in v3)');
|
|
104
|
+
}
|
|
105
|
+
if (devDeps['@agentuity/react']) {
|
|
106
|
+
delete devDeps['@agentuity/react'];
|
|
107
|
+
changes.push('Removed @agentuity/react from devDependencies (deprecated in v3)');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ── 7. Update scripts for new entry point ─────────────────────────
|
|
112
|
+
const scripts = (pkg.scripts ?? {}) as Record<string, string>;
|
|
113
|
+
|
|
114
|
+
// Replace app.ts references in existing scripts
|
|
115
|
+
if (scripts.start && scripts.start.includes('app.ts')) {
|
|
116
|
+
const oldStart = scripts.start;
|
|
117
|
+
scripts.start = scripts.start.replace('app.ts', 'src/index.ts');
|
|
118
|
+
changes.push(`Updated start script: "${oldStart}" → "${scripts.start}"`);
|
|
119
|
+
}
|
|
120
|
+
if (scripts.dev && scripts.dev.includes('app.ts')) {
|
|
121
|
+
const oldDev = scripts.dev;
|
|
122
|
+
scripts.dev = scripts.dev.replace('app.ts', 'src/index.ts');
|
|
123
|
+
changes.push(`Updated dev script: "${oldDev}" → "${scripts.dev}"`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Ensure a start script exists that points to the new entry point.
|
|
127
|
+
// The buildpack's generic detector uses this to determine how to run the app.
|
|
128
|
+
if (
|
|
129
|
+
!scripts.start ||
|
|
130
|
+
scripts.start.includes('.agentuity') ||
|
|
131
|
+
scripts.start.includes('agentuity')
|
|
132
|
+
) {
|
|
133
|
+
const oldStart = scripts.start;
|
|
134
|
+
scripts.start = 'bun src/index.ts';
|
|
135
|
+
if (oldStart) {
|
|
136
|
+
changes.push(`Replaced start script: "${oldStart}" → "${scripts.start}"`);
|
|
137
|
+
} else {
|
|
138
|
+
changes.push(`Added start script: "${scripts.start}"`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Apply dev scripts from dev-setup transform
|
|
143
|
+
if (options?.devScripts) {
|
|
144
|
+
for (const [name, value] of Object.entries(options.devScripts)) {
|
|
145
|
+
const old = scripts[name];
|
|
146
|
+
scripts[name] = value;
|
|
147
|
+
if (old) {
|
|
148
|
+
changes.push(`Updated ${name} script: "${old}" → "${value}"`);
|
|
149
|
+
} else {
|
|
150
|
+
changes.push(`Added ${name} script: "${value}"`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Write back
|
|
156
|
+
if (Object.keys(deps).length > 0) pkg.dependencies = deps;
|
|
157
|
+
if (Object.keys(devDeps).length > 0) pkg.devDependencies = devDeps;
|
|
158
|
+
if (Object.keys(scripts).length > 0) pkg.scripts = scripts;
|
|
159
|
+
|
|
160
|
+
if (changes.length === 0) {
|
|
161
|
+
return { content: null, changes: [] };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Preserve the original indentation style
|
|
165
|
+
const indent = detectIndent(source);
|
|
166
|
+
return {
|
|
167
|
+
content: JSON.stringify(pkg, null, indent) + '\n',
|
|
168
|
+
changes,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Detect indentation (tab vs spaces) from package.json source.
|
|
174
|
+
*/
|
|
175
|
+
function detectIndent(source: string): string | number {
|
|
176
|
+
const match = source.match(/^(\s+)"/m);
|
|
177
|
+
if (match) {
|
|
178
|
+
const whitespace = match[1] ?? '\t';
|
|
179
|
+
if (whitespace.includes('\t')) return '\t';
|
|
180
|
+
return whitespace.length;
|
|
181
|
+
}
|
|
182
|
+
return '\t'; // default to tabs (project convention)
|
|
183
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform: rewrite service access in route files.
|
|
3
|
+
*
|
|
4
|
+
* Replaces c.var.kv, c.var.vector, etc. with direct imports from the
|
|
5
|
+
* shared services module.
|
|
6
|
+
*
|
|
7
|
+
* Uses string-level surgery rather than AST round-trip to preserve
|
|
8
|
+
* formatting and comments.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import ts from 'typescript';
|
|
12
|
+
import type { ServiceUsage } from '../../detect-v3';
|
|
13
|
+
import { relative, dirname } from 'node:path';
|
|
14
|
+
|
|
15
|
+
export interface RouteServiceTransformResult {
|
|
16
|
+
/** The transformed source, or null if no changes */
|
|
17
|
+
source: string | null;
|
|
18
|
+
/** What was changed */
|
|
19
|
+
changes: string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Rewrite c.var.* service access patterns to direct imports.
|
|
24
|
+
*
|
|
25
|
+
* @param source - File source text
|
|
26
|
+
* @param usage - Detected service usage info
|
|
27
|
+
* @param servicesRelativePath - Relative import path to services module (e.g., '../services')
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Remove all imports from @agentuity/runtime.
|
|
31
|
+
* In v3, this package is a deprecation stub — nothing should be imported from it.
|
|
32
|
+
*/
|
|
33
|
+
export function removeRuntimeImports(source: string): { source: string; removed: boolean } {
|
|
34
|
+
const pattern =
|
|
35
|
+
/import\s+(?:type\s+)?\{[^}]*\}\s*from\s*['"]@agentuity\/runtime['"]\s*;?\s*\n?/g;
|
|
36
|
+
const replaced = source.replace(pattern, '');
|
|
37
|
+
return { source: replaced, removed: replaced !== source };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function transformRouteServices(
|
|
41
|
+
source: string,
|
|
42
|
+
usage: ServiceUsage,
|
|
43
|
+
servicesRelativePath: string
|
|
44
|
+
): RouteServiceTransformResult {
|
|
45
|
+
let output = source;
|
|
46
|
+
const changes: string[] = [];
|
|
47
|
+
const servicesAdded = new Set<string>();
|
|
48
|
+
|
|
49
|
+
// Remove @agentuity/runtime imports (Env type, sse, stream, websocket, etc.)
|
|
50
|
+
const runtimeCleanup = removeRuntimeImports(output);
|
|
51
|
+
if (runtimeCleanup.removed) {
|
|
52
|
+
output = runtimeCleanup.source;
|
|
53
|
+
changes.push('Removed @agentuity/runtime imports');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (usage.accessPattern === 'c.var') {
|
|
57
|
+
// Replace c.var.serviceName patterns
|
|
58
|
+
// We need to handle various Hono context variable names: c, ctx, context
|
|
59
|
+
const contextNames = ['c', 'ctx', 'context'];
|
|
60
|
+
|
|
61
|
+
for (const service of usage.services) {
|
|
62
|
+
for (const ctxName of contextNames) {
|
|
63
|
+
// Match: c.var.kv c.var.vector etc.
|
|
64
|
+
const pattern = new RegExp(`\\b${ctxName}\\.var\\.${service}\\b`, 'g');
|
|
65
|
+
if (pattern.test(output)) {
|
|
66
|
+
output = output.replace(pattern, service);
|
|
67
|
+
servicesAdded.add(service);
|
|
68
|
+
changes.push(`Replaced ${ctxName}.var.${service} → ${service}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else if (usage.accessPattern === 'ctx') {
|
|
73
|
+
// Replace ctx.serviceName patterns (agent context)
|
|
74
|
+
const contextNames = ['ctx', 'context', 'c'];
|
|
75
|
+
|
|
76
|
+
for (const service of usage.services) {
|
|
77
|
+
for (const ctxName of contextNames) {
|
|
78
|
+
const pattern = new RegExp(`\\b${ctxName}\\.${service}\\b`, 'g');
|
|
79
|
+
if (pattern.test(output)) {
|
|
80
|
+
output = output.replace(pattern, service);
|
|
81
|
+
servicesAdded.add(service);
|
|
82
|
+
changes.push(`Replaced ${ctxName}.${service} → ${service}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Clean up self-referencing declarations: `const kv = kv;` or `const stream = await stream.create(...)`
|
|
89
|
+
// These happen when the original code had `const kv = c.var.kv;`
|
|
90
|
+
if (servicesAdded.size > 0) {
|
|
91
|
+
for (const service of servicesAdded) {
|
|
92
|
+
// Pattern: const/let/var service = service; (entire line)
|
|
93
|
+
const selfRefPattern = new RegExp(
|
|
94
|
+
`^\\s*(?:const|let|var)\\s+${service}\\s*=\\s*${service}\\s*;?\\s*$`,
|
|
95
|
+
'gm'
|
|
96
|
+
);
|
|
97
|
+
if (selfRefPattern.test(output)) {
|
|
98
|
+
output = output.replace(selfRefPattern, '');
|
|
99
|
+
changes.push(`Removed self-referencing declaration: const ${service} = ${service}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Add import for services if any were rewritten
|
|
105
|
+
if (servicesAdded.size > 0) {
|
|
106
|
+
const importList = [...servicesAdded].sort().join(', ');
|
|
107
|
+
const importLine = `import { ${importList} } from '${servicesRelativePath}';`;
|
|
108
|
+
|
|
109
|
+
// Check if there's already an import from the services module
|
|
110
|
+
const existingServicesImport = new RegExp(
|
|
111
|
+
`import\\s*\\{[^}]*\\}\\s*from\\s*['"]${escapeRegex(servicesRelativePath)}['"]`
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
if (existingServicesImport.test(output)) {
|
|
115
|
+
// Merge with existing import
|
|
116
|
+
output = output.replace(existingServicesImport, (match) => {
|
|
117
|
+
// Extract existing imports
|
|
118
|
+
const existingMatch = match.match(/\{([^}]*)\}/);
|
|
119
|
+
if (!existingMatch) return match;
|
|
120
|
+
const existing = existingMatch[1]!
|
|
121
|
+
.split(',')
|
|
122
|
+
.map((s) => s.trim())
|
|
123
|
+
.filter(Boolean);
|
|
124
|
+
const merged = [...new Set([...existing, ...servicesAdded])].sort();
|
|
125
|
+
return `import { ${merged.join(', ')} } from '${servicesRelativePath}'`;
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
// Insert new import after existing imports
|
|
129
|
+
output = insertAfterImports(output, importLine);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
changes.push(`Added import for: ${importList}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (changes.length === 0) {
|
|
136
|
+
return { source: null, changes: [] };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { source: output, changes };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Compute the relative import path from a source file to src/services.ts.
|
|
144
|
+
*/
|
|
145
|
+
export function computeServicesRelativePath(projectDir: string, sourceFilePath: string): string {
|
|
146
|
+
const servicesPath = 'src/services';
|
|
147
|
+
const sourceDir = dirname(relative(projectDir, sourceFilePath));
|
|
148
|
+
|
|
149
|
+
let rel = relative(sourceDir, servicesPath);
|
|
150
|
+
// Ensure it starts with ./ or ../
|
|
151
|
+
if (!rel.startsWith('.')) {
|
|
152
|
+
rel = './' + rel;
|
|
153
|
+
}
|
|
154
|
+
// Remove .ts extension if present
|
|
155
|
+
rel = rel.replace(/\.ts$/, '');
|
|
156
|
+
|
|
157
|
+
return rel;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// Helpers
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
function insertAfterImports(source: string, importLine: string): string {
|
|
165
|
+
const sf = ts.createSourceFile('temp.ts', source, ts.ScriptTarget.ESNext, true);
|
|
166
|
+
|
|
167
|
+
let lastImportEnd = -1;
|
|
168
|
+
for (const stmt of sf.statements) {
|
|
169
|
+
if (ts.isImportDeclaration(stmt)) {
|
|
170
|
+
lastImportEnd = stmt.getEnd();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (lastImportEnd >= 0) {
|
|
175
|
+
return (
|
|
176
|
+
source.substring(0, lastImportEnd) + '\n' + importLine + source.substring(lastImportEnd)
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return importLine + '\n' + source;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function escapeRegex(str: string): string {
|
|
184
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
185
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform: generate src/services.ts
|
|
3
|
+
*
|
|
4
|
+
* Creates a shared services module that exports singleton client instances
|
|
5
|
+
* for all Agentuity services detected in use across the project.
|
|
6
|
+
*
|
|
7
|
+
* Only includes services that are actually used — no unnecessary dependencies.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SERVICE_PACKAGE_MAP } from '../../detect-v3';
|
|
11
|
+
|
|
12
|
+
export interface ServicesFileResult {
|
|
13
|
+
/** Generated source for src/services.ts, or null if no services used */
|
|
14
|
+
source: string | null;
|
|
15
|
+
/** What was included */
|
|
16
|
+
changes: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate src/services.ts based on detected service usage.
|
|
21
|
+
*/
|
|
22
|
+
export function generateServicesFile(servicesUsed: string[]): ServicesFileResult {
|
|
23
|
+
if (servicesUsed.length === 0) {
|
|
24
|
+
return { source: null, changes: [] };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const changes: string[] = [];
|
|
28
|
+
const imports: string[] = [];
|
|
29
|
+
const exports: string[] = [];
|
|
30
|
+
|
|
31
|
+
// Header comment
|
|
32
|
+
const header = [
|
|
33
|
+
'/**',
|
|
34
|
+
' * Shared Agentuity service clients.',
|
|
35
|
+
' *',
|
|
36
|
+
' * Auto-generated by @agentuity/migrate (v2 → v3 migration).',
|
|
37
|
+
' * Each client auto-configures from AGENTUITY_* environment variables.',
|
|
38
|
+
' *',
|
|
39
|
+
' * Usage:',
|
|
40
|
+
" * import { kv, vector } from './services';",
|
|
41
|
+
" * const data = await kv.get('namespace', 'key');",
|
|
42
|
+
' */',
|
|
43
|
+
'',
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// Logger is special — comes from @agentuity/telemetry
|
|
47
|
+
const hasLogger = servicesUsed.includes('logger');
|
|
48
|
+
const serviceClients = servicesUsed.filter((s) => s !== 'logger');
|
|
49
|
+
|
|
50
|
+
// Generate import + export for each service client
|
|
51
|
+
for (const service of serviceClients.sort()) {
|
|
52
|
+
const mapping = SERVICE_PACKAGE_MAP[service];
|
|
53
|
+
if (!mapping) continue;
|
|
54
|
+
|
|
55
|
+
imports.push(`import { ${mapping.client} } from '${mapping.pkg}';`);
|
|
56
|
+
exports.push(`export const ${service} = new ${mapping.client}();`);
|
|
57
|
+
changes.push(`Added ${service} client from ${mapping.pkg}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Logger from telemetry
|
|
61
|
+
if (hasLogger) {
|
|
62
|
+
imports.push("import { register } from '@agentuity/telemetry';");
|
|
63
|
+
exports.push('');
|
|
64
|
+
exports.push('/** Shared logger instance from telemetry */');
|
|
65
|
+
exports.push('const telemetry = register();');
|
|
66
|
+
exports.push('export const logger = telemetry.logger;');
|
|
67
|
+
changes.push('Added logger from @agentuity/telemetry');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const lines = [...header, ...imports, '', ...exports, ''];
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
source: lines.join('\n'),
|
|
74
|
+
changes,
|
|
75
|
+
};
|
|
76
|
+
}
|