(
tag: string,
templateName: string,
agentsRequested?: readonly string[],
)
| 96 | constructor(private readonly opts: CreatorOptions) {} |
| 97 | |
| 98 | async create( |
| 99 | tag: string, |
| 100 | templateName: string, |
| 101 | agentsRequested?: readonly string[], |
| 102 | ): Promise<CreateResult> { |
| 103 | if (!TAG_RE.test(tag)) { |
| 104 | return { |
| 105 | ok: false, |
| 106 | code: 'invalid_tag', |
| 107 | message: `tag must match ${TAG_RE.source}`, |
| 108 | }; |
| 109 | } |
| 110 | if (this.opts.registry.hasTag(tag)) { |
| 111 | return { ok: false, code: 'tag_in_use', message: `tag in use: ${tag}` }; |
| 112 | } |
| 113 | const template = this.opts.templateRegistry.get(templateName); |
| 114 | if (!template) { |
| 115 | return { |
| 116 | ok: false, |
| 117 | code: 'unknown_template', |
| 118 | message: `unknown template: ${templateName}`, |
| 119 | }; |
| 120 | } |
| 121 | |
| 122 | // Agent policy lives in `resolveCreateAgents` (this file) so every create |
| 123 | // path — form, quick-chat, headless — converges on it. |
| 124 | const agents = resolveCreateAgents( |
| 125 | agentsRequested, |
| 126 | template.defaultAgents, |
| 127 | this.opts.adapterRegistry.list().map((a) => a.id), |
| 128 | ); |
| 129 | |
| 130 | // Validate every requested adapter exists in the registry. |
| 131 | for (const a of agents) { |
| 132 | if (!this.opts.adapterRegistry.get(a)) { |
| 133 | return { |
| 134 | ok: false, |
| 135 | code: 'unknown_agent', |
| 136 | message: `unknown agent: ${a}`, |
| 137 | }; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | const id = generatePetnameId(templateName, { |
| 142 | fallbackPrefix: 'workspace', |
| 143 | isTaken: (candidate) => |
| 144 | this.opts.registry.hasId(candidate) || |
| 145 | existsSync(join(this.opts.workspacesRoot, candidate)), |
| 146 | }); |
| 147 | const dir = join(this.opts.workspacesRoot, id); |
| 148 | const log = this.opts.logger.child({ tag, id, dir, template: templateName, agents }); |
| 149 | |
| 150 | log.info('bootstrap.start', { script: template.bootstrapScript }); |
| 151 | |
| 152 | const result = await runScript( |
| 153 | template.bootstrapScript, |
| 154 | [tag, dir], |
| 155 | { |
nothing calls this directly
no test coverage detected