Skip to content

Commit ae6154e

Browse files
committed
ignore: rework bootstrap so server lazy starts it
1 parent 0e19ca2 commit ae6154e

13 files changed

Lines changed: 671 additions & 618 deletions

File tree

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
1-
import { Format } from "../format"
2-
import { LSP } from "../lsp"
3-
import { Plugin } from "../plugin"
1+
import { InstanceBootstrap } from "../project/bootstrap"
42
import { Instance } from "../project/instance"
5-
import { Share } from "../share/share"
6-
import { Snapshot } from "../snapshot"
73

84
export async function bootstrap<T>(directory: string, cb: () => Promise<T>) {
9-
return Instance.provide(directory, async () => {
10-
await Plugin.init()
11-
Share.init()
12-
Format.init()
13-
LSP.init()
14-
Snapshot.init()
15-
const result = await cb()
16-
await Instance.dispose()
17-
return result
5+
return Instance.provide({
6+
directory,
7+
init: InstanceBootstrap,
8+
fn: async () => {
9+
const result = await cb()
10+
await Instance.dispose()
11+
return result
12+
},
1813
})
1914
}

packages/opencode/src/cli/cmd/agent.ts

Lines changed: 104 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -11,121 +11,124 @@ const AgentCreateCommand = cmd({
1111
command: "create",
1212
describe: "create a new agent",
1313
async handler() {
14-
await Instance.provide(process.cwd(), async () => {
15-
UI.empty()
16-
prompts.intro("Create agent")
17-
const project = Instance.project
14+
await Instance.provide({
15+
directory: process.cwd(),
16+
async fn() {
17+
UI.empty()
18+
prompts.intro("Create agent")
19+
const project = Instance.project
1820

19-
let scope: "global" | "project" = "global"
20-
if (project.vcs === "git") {
21-
const scopeResult = await prompts.select({
22-
message: "Location",
21+
let scope: "global" | "project" = "global"
22+
if (project.vcs === "git") {
23+
const scopeResult = await prompts.select({
24+
message: "Location",
25+
options: [
26+
{
27+
label: "Current project",
28+
value: "project" as const,
29+
hint: Instance.worktree,
30+
},
31+
{
32+
label: "Global",
33+
value: "global" as const,
34+
hint: Global.Path.config,
35+
},
36+
],
37+
})
38+
if (prompts.isCancel(scopeResult)) throw new UI.CancelledError()
39+
scope = scopeResult
40+
}
41+
42+
const query = await prompts.text({
43+
message: "Description",
44+
placeholder: "What should this agent do?",
45+
validate: (x) => (x && x.length > 0 ? undefined : "Required"),
46+
})
47+
if (prompts.isCancel(query)) throw new UI.CancelledError()
48+
49+
const spinner = prompts.spinner()
50+
51+
spinner.start("Generating agent configuration...")
52+
const generated = await Agent.generate({ description: query }).catch((error) => {
53+
spinner.stop(`LLM failed to generate agent: ${error.message}`, 1)
54+
throw new UI.CancelledError()
55+
})
56+
spinner.stop(`Agent ${generated.identifier} generated`)
57+
58+
const availableTools = [
59+
"bash",
60+
"read",
61+
"write",
62+
"edit",
63+
"list",
64+
"glob",
65+
"grep",
66+
"webfetch",
67+
"task",
68+
"todowrite",
69+
"todoread",
70+
]
71+
72+
const selectedTools = await prompts.multiselect({
73+
message: "Select tools to enable",
74+
options: availableTools.map((tool) => ({
75+
label: tool,
76+
value: tool,
77+
})),
78+
initialValues: availableTools,
79+
})
80+
if (prompts.isCancel(selectedTools)) throw new UI.CancelledError()
81+
82+
const modeResult = await prompts.select({
83+
message: "Agent mode",
2384
options: [
2485
{
25-
label: "Current project",
26-
value: "project" as const,
27-
hint: Instance.worktree,
86+
label: "All",
87+
value: "all" as const,
88+
hint: "Can function in both primary and subagent roles",
2889
},
2990
{
30-
label: "Global",
31-
value: "global" as const,
32-
hint: Global.Path.config,
91+
label: "Primary",
92+
value: "primary" as const,
93+
hint: "Acts as a primary/main agent",
94+
},
95+
{
96+
label: "Subagent",
97+
value: "subagent" as const,
98+
hint: "Can be used as a subagent by other agents",
3399
},
34100
],
101+
initialValue: "all",
35102
})
36-
if (prompts.isCancel(scopeResult)) throw new UI.CancelledError()
37-
scope = scopeResult
38-
}
39-
40-
const query = await prompts.text({
41-
message: "Description",
42-
placeholder: "What should this agent do?",
43-
validate: (x) => (x && x.length > 0 ? undefined : "Required"),
44-
})
45-
if (prompts.isCancel(query)) throw new UI.CancelledError()
46-
47-
const spinner = prompts.spinner()
48-
49-
spinner.start("Generating agent configuration...")
50-
const generated = await Agent.generate({ description: query }).catch((error) => {
51-
spinner.stop(`LLM failed to generate agent: ${error.message}`, 1)
52-
throw new UI.CancelledError()
53-
})
54-
spinner.stop(`Agent ${generated.identifier} generated`)
103+
if (prompts.isCancel(modeResult)) throw new UI.CancelledError()
55104

56-
const availableTools = [
57-
"bash",
58-
"read",
59-
"write",
60-
"edit",
61-
"list",
62-
"glob",
63-
"grep",
64-
"webfetch",
65-
"task",
66-
"todowrite",
67-
"todoread",
68-
]
69-
70-
const selectedTools = await prompts.multiselect({
71-
message: "Select tools to enable",
72-
options: availableTools.map((tool) => ({
73-
label: tool,
74-
value: tool,
75-
})),
76-
initialValues: availableTools,
77-
})
78-
if (prompts.isCancel(selectedTools)) throw new UI.CancelledError()
79-
80-
const modeResult = await prompts.select({
81-
message: "Agent mode",
82-
options: [
83-
{
84-
label: "All",
85-
value: "all" as const,
86-
hint: "Can function in both primary and subagent roles",
87-
},
88-
{
89-
label: "Primary",
90-
value: "primary" as const,
91-
hint: "Acts as a primary/main agent",
92-
},
93-
{
94-
label: "Subagent",
95-
value: "subagent" as const,
96-
hint: "Can be used as a subagent by other agents",
97-
},
98-
],
99-
initialValue: "all",
100-
})
101-
if (prompts.isCancel(modeResult)) throw new UI.CancelledError()
102-
103-
const tools: Record<string, boolean> = {}
104-
for (const tool of availableTools) {
105-
if (!selectedTools.includes(tool)) {
106-
tools[tool] = false
105+
const tools: Record<string, boolean> = {}
106+
for (const tool of availableTools) {
107+
if (!selectedTools.includes(tool)) {
108+
tools[tool] = false
109+
}
107110
}
108-
}
109111

110-
const frontmatter: any = {
111-
description: generated.whenToUse,
112-
mode: modeResult,
113-
}
114-
if (Object.keys(tools).length > 0) {
115-
frontmatter.tools = tools
116-
}
112+
const frontmatter: any = {
113+
description: generated.whenToUse,
114+
mode: modeResult,
115+
}
116+
if (Object.keys(tools).length > 0) {
117+
frontmatter.tools = tools
118+
}
117119

118-
const content = matter.stringify(generated.systemPrompt, frontmatter)
119-
const filePath = path.join(
120-
scope === "global" ? Global.Path.config : path.join(Instance.worktree, ".opencode"),
121-
`agent`,
122-
`${generated.identifier}.md`,
123-
)
120+
const content = matter.stringify(generated.systemPrompt, frontmatter)
121+
const filePath = path.join(
122+
scope === "global" ? Global.Path.config : path.join(Instance.worktree, ".opencode"),
123+
`agent`,
124+
`${generated.identifier}.md`,
125+
)
124126

125-
await Bun.write(filePath, content)
127+
await Bun.write(filePath, content)
126128

127-
prompts.log.success(`Agent created: ${filePath}`)
128-
prompts.outro("Done")
129+
prompts.log.success(`Agent created: ${filePath}`)
130+
prompts.outro("Done")
131+
},
129132
})
130133
},
131134
})

0 commit comments

Comments
 (0)