- Updated all package.json name fields and dependency references - Updated all TypeScript/JavaScript imports - Updated .woodpecker/publish.yml filters and registry paths - Updated tools/install.sh scope default - Updated .npmrc registry paths (worktree + host) - Enhanced update-checker.ts with checkForAllUpdates() multi-package support - Updated CLI update command to show table of all packages - Added KNOWN_PACKAGES, formatAllPackagesTable, getInstallAllCommand - Marked checkForUpdate() with @deprecated JSDoc Closes #391
99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import { Inject, Injectable, Logger } from '@nestjs/common';
|
|
import type { Brain } from '@mosaicstack/brain';
|
|
import { BRAIN } from '../brain/brain.tokens.js';
|
|
import { PluginService } from '../plugin/plugin.service.js';
|
|
import { WorkspaceService } from './workspace.service.js';
|
|
|
|
export interface BootstrapProjectParams {
|
|
name: string;
|
|
description?: string;
|
|
userId: string;
|
|
teamId?: string;
|
|
repoUrl?: string;
|
|
}
|
|
|
|
export interface BootstrapProjectResult {
|
|
projectId: string;
|
|
workspacePath: string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class ProjectBootstrapService {
|
|
private readonly logger = new Logger(ProjectBootstrapService.name);
|
|
|
|
constructor(
|
|
@Inject(BRAIN) private readonly brain: Brain,
|
|
private readonly workspace: WorkspaceService,
|
|
private readonly pluginService: PluginService,
|
|
) {}
|
|
|
|
/**
|
|
* Bootstrap a new project: create DB record + workspace directory.
|
|
* Returns the created project with its workspace path.
|
|
*/
|
|
async bootstrap(params: BootstrapProjectParams): Promise<BootstrapProjectResult> {
|
|
const ownerType: 'user' | 'team' = params.teamId ? 'team' : 'user';
|
|
|
|
this.logger.log(
|
|
`Bootstrapping project "${params.name}" for ${ownerType} ${params.teamId ?? params.userId}`,
|
|
);
|
|
|
|
// 1. Create DB record
|
|
const project = await this.brain.projects.create({
|
|
name: params.name,
|
|
description: params.description,
|
|
ownerId: params.userId,
|
|
teamId: params.teamId ?? null,
|
|
ownerType,
|
|
});
|
|
|
|
// 2. Create workspace directory (includes docs structure)
|
|
const workspacePath = await this.workspace.create(
|
|
{
|
|
id: project.id,
|
|
ownerType,
|
|
userId: params.userId,
|
|
teamId: params.teamId ?? null,
|
|
},
|
|
params.repoUrl,
|
|
);
|
|
|
|
// 3. Create default agent config for the project
|
|
await this.brain.agents.create({
|
|
name: 'default',
|
|
provider: '',
|
|
model: '',
|
|
projectId: project.id,
|
|
ownerId: params.userId,
|
|
isSystem: false,
|
|
status: 'active',
|
|
});
|
|
|
|
// 4. Notify plugins so they can set up project-specific resources (e.g. Discord channel)
|
|
try {
|
|
for (const plugin of this.pluginService.getPlugins()) {
|
|
if (plugin.onProjectCreated) {
|
|
const result = await plugin.onProjectCreated({
|
|
id: project.id,
|
|
name: params.name,
|
|
description: params.description,
|
|
});
|
|
if (result?.channelId) {
|
|
await this.brain.projects.update(project.id, {
|
|
metadata: { discordChannelId: result.channelId },
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
this.logger.warn(
|
|
`Plugin project notification failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
);
|
|
}
|
|
|
|
this.logger.log(`Project ${project.id} bootstrapped at ${workspacePath}`);
|
|
|
|
return { projectId: project.id, workspacePath };
|
|
}
|
|
}
|