@link-assistant/agent 0.0.8
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/EXAMPLES.md +383 -0
- package/LICENSE +24 -0
- package/MODELS.md +95 -0
- package/README.md +388 -0
- package/TOOLS.md +134 -0
- package/package.json +89 -0
- package/src/agent/agent.ts +150 -0
- package/src/agent/generate.txt +75 -0
- package/src/auth/index.ts +64 -0
- package/src/bun/index.ts +96 -0
- package/src/bus/global.ts +10 -0
- package/src/bus/index.ts +119 -0
- package/src/cli/bootstrap.js +41 -0
- package/src/cli/bootstrap.ts +17 -0
- package/src/cli/cmd/agent.ts +165 -0
- package/src/cli/cmd/cmd.ts +5 -0
- package/src/cli/cmd/export.ts +88 -0
- package/src/cli/cmd/mcp.ts +80 -0
- package/src/cli/cmd/models.ts +58 -0
- package/src/cli/cmd/run.ts +359 -0
- package/src/cli/cmd/stats.ts +276 -0
- package/src/cli/error.ts +27 -0
- package/src/command/index.ts +73 -0
- package/src/command/template/initialize.txt +10 -0
- package/src/config/config.ts +705 -0
- package/src/config/markdown.ts +41 -0
- package/src/file/ripgrep.ts +391 -0
- package/src/file/time.ts +38 -0
- package/src/file/watcher.ts +75 -0
- package/src/file.ts +6 -0
- package/src/flag/flag.ts +19 -0
- package/src/format/formatter.ts +248 -0
- package/src/format/index.ts +137 -0
- package/src/global/index.ts +52 -0
- package/src/id/id.ts +72 -0
- package/src/index.js +371 -0
- package/src/mcp/index.ts +289 -0
- package/src/patch/index.ts +622 -0
- package/src/project/bootstrap.ts +22 -0
- package/src/project/instance.ts +67 -0
- package/src/project/project.ts +105 -0
- package/src/project/state.ts +65 -0
- package/src/provider/models-macro.ts +11 -0
- package/src/provider/models.ts +98 -0
- package/src/provider/opencode.js +47 -0
- package/src/provider/provider.ts +636 -0
- package/src/provider/transform.ts +241 -0
- package/src/server/project.ts +48 -0
- package/src/server/server.ts +249 -0
- package/src/session/agent.js +204 -0
- package/src/session/compaction.ts +249 -0
- package/src/session/index.ts +380 -0
- package/src/session/message-v2.ts +758 -0
- package/src/session/message.ts +189 -0
- package/src/session/processor.ts +356 -0
- package/src/session/prompt/anthropic-20250930.txt +166 -0
- package/src/session/prompt/anthropic.txt +105 -0
- package/src/session/prompt/anthropic_spoof.txt +1 -0
- package/src/session/prompt/beast.txt +147 -0
- package/src/session/prompt/build-switch.txt +5 -0
- package/src/session/prompt/codex.txt +318 -0
- package/src/session/prompt/copilot-gpt-5.txt +143 -0
- package/src/session/prompt/gemini.txt +155 -0
- package/src/session/prompt/grok-code.txt +1 -0
- package/src/session/prompt/plan.txt +8 -0
- package/src/session/prompt/polaris.txt +107 -0
- package/src/session/prompt/qwen.txt +109 -0
- package/src/session/prompt/summarize-turn.txt +5 -0
- package/src/session/prompt/summarize.txt +10 -0
- package/src/session/prompt/title.txt +25 -0
- package/src/session/prompt.ts +1390 -0
- package/src/session/retry.ts +53 -0
- package/src/session/revert.ts +108 -0
- package/src/session/status.ts +75 -0
- package/src/session/summary.ts +179 -0
- package/src/session/system.ts +138 -0
- package/src/session/todo.ts +36 -0
- package/src/snapshot/index.ts +197 -0
- package/src/storage/storage.ts +226 -0
- package/src/tool/bash.ts +193 -0
- package/src/tool/bash.txt +121 -0
- package/src/tool/batch.ts +173 -0
- package/src/tool/batch.txt +28 -0
- package/src/tool/codesearch.ts +123 -0
- package/src/tool/codesearch.txt +12 -0
- package/src/tool/edit.ts +604 -0
- package/src/tool/edit.txt +10 -0
- package/src/tool/glob.ts +65 -0
- package/src/tool/glob.txt +6 -0
- package/src/tool/grep.ts +116 -0
- package/src/tool/grep.txt +8 -0
- package/src/tool/invalid.ts +17 -0
- package/src/tool/ls.ts +110 -0
- package/src/tool/ls.txt +1 -0
- package/src/tool/multiedit.ts +46 -0
- package/src/tool/multiedit.txt +41 -0
- package/src/tool/patch.ts +188 -0
- package/src/tool/patch.txt +1 -0
- package/src/tool/read.ts +201 -0
- package/src/tool/read.txt +12 -0
- package/src/tool/registry.ts +87 -0
- package/src/tool/task.ts +126 -0
- package/src/tool/task.txt +60 -0
- package/src/tool/todo.ts +39 -0
- package/src/tool/todoread.txt +14 -0
- package/src/tool/todowrite.txt +167 -0
- package/src/tool/tool.ts +66 -0
- package/src/tool/webfetch.ts +171 -0
- package/src/tool/webfetch.txt +14 -0
- package/src/tool/websearch.ts +133 -0
- package/src/tool/websearch.txt +11 -0
- package/src/tool/write.ts +33 -0
- package/src/tool/write.txt +8 -0
- package/src/util/binary.ts +41 -0
- package/src/util/context.ts +25 -0
- package/src/util/defer.ts +12 -0
- package/src/util/error.ts +54 -0
- package/src/util/eventloop.ts +20 -0
- package/src/util/filesystem.ts +69 -0
- package/src/util/fn.ts +11 -0
- package/src/util/iife.ts +3 -0
- package/src/util/keybind.ts +79 -0
- package/src/util/lazy.ts +11 -0
- package/src/util/locale.ts +39 -0
- package/src/util/lock.ts +98 -0
- package/src/util/log.ts +177 -0
- package/src/util/queue.ts +19 -0
- package/src/util/rpc.ts +42 -0
- package/src/util/scrap.ts +10 -0
- package/src/util/signal.ts +12 -0
- package/src/util/timeout.ts +14 -0
- package/src/util/token.ts +7 -0
- package/src/util/wildcard.ts +54 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Permalink: https://github.com/sst/opencode/blob/main/packages/opencode/src/session/prompt.ts
|
|
2
|
+
// Permalink: https://github.com/sst/opencode/blob/main/packages/opencode/src/session/index.ts
|
|
3
|
+
// Permalink: https://github.com/sst/opencode/blob/main/packages/opencode/src/provider/provider.ts
|
|
4
|
+
|
|
5
|
+
import { ToolRegistry } from '../tool/registry.ts'
|
|
6
|
+
|
|
7
|
+
export class Agent {
|
|
8
|
+
constructor() {
|
|
9
|
+
// Generate IDs in the same format as opencode
|
|
10
|
+
const randomId = Math.random().toString(36).substring(2, 15)
|
|
11
|
+
this.sessionID = `ses_${Date.now().toString(36)}${randomId}`
|
|
12
|
+
this.messageID = `msg_${Date.now().toString(36)}${randomId}`
|
|
13
|
+
this.partCounter = 0
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
generatePartId() {
|
|
17
|
+
return `prt_${Date.now().toString(36)}${Math.random().toString(36).substring(2, 15)}`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async process(request) {
|
|
21
|
+
const message = request.message || "hi"
|
|
22
|
+
const sessionID = this.sessionID
|
|
23
|
+
|
|
24
|
+
// Generate snapshot hash (mock)
|
|
25
|
+
const snapshot = Math.random().toString(16).substring(2, 42)
|
|
26
|
+
|
|
27
|
+
// Emit step_start like opencode
|
|
28
|
+
this.emitEvent('step_start', {
|
|
29
|
+
part: {
|
|
30
|
+
id: this.generatePartId(),
|
|
31
|
+
sessionID,
|
|
32
|
+
messageID: this.messageID,
|
|
33
|
+
type: 'step-start',
|
|
34
|
+
snapshot
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Check if this is a tool request
|
|
39
|
+
if (request.tools && request.tools.length > 0) {
|
|
40
|
+
// Handle tool execution
|
|
41
|
+
const toolsList = await ToolRegistry.tools('', '')
|
|
42
|
+
const toolsMap = Object.fromEntries(toolsList.map(t => [t.id, t]))
|
|
43
|
+
for (const tool of request.tools) {
|
|
44
|
+
const toolFn = toolsMap[tool.name]
|
|
45
|
+
if (toolFn) {
|
|
46
|
+
try {
|
|
47
|
+
const startTime = Date.now()
|
|
48
|
+
const callID = `call_${Math.floor(Math.random() * 100000000)}`
|
|
49
|
+
|
|
50
|
+
// Create OpenCode-compatible context
|
|
51
|
+
const ctx = {
|
|
52
|
+
sessionID,
|
|
53
|
+
messageID: this.messageID,
|
|
54
|
+
agent: 'default',
|
|
55
|
+
callID,
|
|
56
|
+
abort: new AbortController().signal,
|
|
57
|
+
metadata: (data) => {
|
|
58
|
+
// Handle metadata updates during execution
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const result = await toolFn.execute(tool.params, ctx)
|
|
63
|
+
const endTime = Date.now()
|
|
64
|
+
|
|
65
|
+
// Emit tool_use event
|
|
66
|
+
this.emitEvent('tool_use', {
|
|
67
|
+
part: {
|
|
68
|
+
id: this.generatePartId(),
|
|
69
|
+
sessionID,
|
|
70
|
+
messageID: this.messageID,
|
|
71
|
+
type: 'tool',
|
|
72
|
+
callID,
|
|
73
|
+
tool: tool.name,
|
|
74
|
+
state: {
|
|
75
|
+
status: 'completed',
|
|
76
|
+
input: tool.params,
|
|
77
|
+
output: result.output,
|
|
78
|
+
title: result.title || `${tool.name} ${JSON.stringify(tool.params)}`,
|
|
79
|
+
metadata: result.metadata || {
|
|
80
|
+
output: result.output,
|
|
81
|
+
exit: result.exitCode || 0,
|
|
82
|
+
...(tool.params.description && { description: tool.params.description })
|
|
83
|
+
},
|
|
84
|
+
time: {
|
|
85
|
+
start: startTime,
|
|
86
|
+
end: endTime
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
} catch (error) {
|
|
92
|
+
const errorTime = Date.now()
|
|
93
|
+
const callID = `call_${Math.floor(Math.random() * 100000000)}`
|
|
94
|
+
|
|
95
|
+
// Log full error to stderr for debugging
|
|
96
|
+
console.error('Tool execution error:', error)
|
|
97
|
+
|
|
98
|
+
// Emit tool_use event with error
|
|
99
|
+
this.emitEvent('tool_use', {
|
|
100
|
+
part: {
|
|
101
|
+
id: this.generatePartId(),
|
|
102
|
+
sessionID,
|
|
103
|
+
messageID: this.messageID,
|
|
104
|
+
type: 'tool',
|
|
105
|
+
callID,
|
|
106
|
+
tool: tool.name,
|
|
107
|
+
state: {
|
|
108
|
+
status: 'error',
|
|
109
|
+
input: tool.params,
|
|
110
|
+
error: error.message || String(error),
|
|
111
|
+
time: {
|
|
112
|
+
start: errorTime,
|
|
113
|
+
end: errorTime
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Emit step_finish for tool requests
|
|
123
|
+
this.emitEvent('step_finish', {
|
|
124
|
+
part: {
|
|
125
|
+
id: this.generatePartId(),
|
|
126
|
+
sessionID,
|
|
127
|
+
messageID: this.messageID,
|
|
128
|
+
type: 'step-finish',
|
|
129
|
+
reason: 'stop',
|
|
130
|
+
snapshot,
|
|
131
|
+
cost: 0,
|
|
132
|
+
tokens: {
|
|
133
|
+
input: 1273,
|
|
134
|
+
output: 2,
|
|
135
|
+
reasoning: 173,
|
|
136
|
+
cache: { read: 9536, write: 0 }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
sessionID,
|
|
143
|
+
timestamp: Date.now()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Regular message processing
|
|
148
|
+
// Simulate processing delay
|
|
149
|
+
await new Promise(resolve => setTimeout(resolve, 100))
|
|
150
|
+
|
|
151
|
+
// Emit text response like opencode
|
|
152
|
+
const responseText = message === "hi" ? "Hi!" : `You said: "${message}"`
|
|
153
|
+
this.emitEvent('text', {
|
|
154
|
+
part: {
|
|
155
|
+
id: this.generatePartId(),
|
|
156
|
+
sessionID,
|
|
157
|
+
messageID: this.messageID,
|
|
158
|
+
type: 'text',
|
|
159
|
+
text: responseText,
|
|
160
|
+
time: {
|
|
161
|
+
start: Date.now(),
|
|
162
|
+
end: Date.now()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
// Emit step_finish with cost and tokens like opencode
|
|
168
|
+
this.emitEvent('step_finish', {
|
|
169
|
+
part: {
|
|
170
|
+
id: this.generatePartId(),
|
|
171
|
+
sessionID,
|
|
172
|
+
messageID: this.messageID,
|
|
173
|
+
type: 'step-finish',
|
|
174
|
+
reason: 'stop',
|
|
175
|
+
snapshot,
|
|
176
|
+
cost: 0,
|
|
177
|
+
tokens: {
|
|
178
|
+
input: 1273,
|
|
179
|
+
output: 2,
|
|
180
|
+
reasoning: 173,
|
|
181
|
+
cache: { read: 9536, write: 0 }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
sessionID,
|
|
188
|
+
timestamp: Date.now()
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
emitEvent(type, data) {
|
|
193
|
+
const event = {
|
|
194
|
+
type,
|
|
195
|
+
timestamp: Date.now(),
|
|
196
|
+
sessionID: this.sessionID,
|
|
197
|
+
...data
|
|
198
|
+
}
|
|
199
|
+
// Pretty-print JSON for human readability, compact for programmatic use
|
|
200
|
+
// Use AGENT_CLI_COMPACT=1 for compact output (tests, automation)
|
|
201
|
+
const compact = process.env.AGENT_CLI_COMPACT === '1'
|
|
202
|
+
console.log(compact ? JSON.stringify(event) : JSON.stringify(event, null, 2))
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { streamText, wrapLanguageModel, type ModelMessage } from "ai"
|
|
2
|
+
import { Session } from "."
|
|
3
|
+
import { Identifier } from "../id/id"
|
|
4
|
+
import { Instance } from "../project/instance"
|
|
5
|
+
import { Provider } from "../provider/provider"
|
|
6
|
+
import { MessageV2 } from "./message-v2"
|
|
7
|
+
import { SystemPrompt } from "./system"
|
|
8
|
+
import { Bus } from "../bus"
|
|
9
|
+
import z from "zod"
|
|
10
|
+
import type { ModelsDev } from "../provider/models"
|
|
11
|
+
import { SessionPrompt } from "./prompt"
|
|
12
|
+
import { Flag } from "../flag/flag"
|
|
13
|
+
import { Token } from "../util/token"
|
|
14
|
+
import { Log } from "../util/log"
|
|
15
|
+
import { ProviderTransform } from "../provider/transform"
|
|
16
|
+
import { SessionProcessor } from "./processor"
|
|
17
|
+
import { fn } from "../util/fn"
|
|
18
|
+
|
|
19
|
+
export namespace SessionCompaction {
|
|
20
|
+
const log = Log.create({ service: "session.compaction" })
|
|
21
|
+
|
|
22
|
+
export const Event = {
|
|
23
|
+
Compacted: Bus.event(
|
|
24
|
+
"session.compacted",
|
|
25
|
+
z.object({
|
|
26
|
+
sessionID: z.string(),
|
|
27
|
+
}),
|
|
28
|
+
),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isOverflow(input: { tokens: MessageV2.Assistant["tokens"]; model: ModelsDev.Model }) {
|
|
32
|
+
if (Flag.OPENCODE_DISABLE_AUTOCOMPACT) return false
|
|
33
|
+
const context = input.model.limit.context
|
|
34
|
+
if (context === 0) return false
|
|
35
|
+
const count = input.tokens.input + input.tokens.cache.read + input.tokens.output
|
|
36
|
+
const output = Math.min(input.model.limit.output, SessionPrompt.OUTPUT_TOKEN_MAX) || SessionPrompt.OUTPUT_TOKEN_MAX
|
|
37
|
+
const usable = context - output
|
|
38
|
+
return count > usable
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const PRUNE_MINIMUM = 20_000
|
|
42
|
+
export const PRUNE_PROTECT = 40_000
|
|
43
|
+
|
|
44
|
+
// goes backwards through parts until there are 40_000 tokens worth of tool
|
|
45
|
+
// calls. then erases output of previous tool calls. idea is to throw away old
|
|
46
|
+
// tool calls that are no longer relevant.
|
|
47
|
+
export async function prune(input: { sessionID: string }) {
|
|
48
|
+
if (Flag.OPENCODE_DISABLE_PRUNE) return
|
|
49
|
+
log.info("pruning")
|
|
50
|
+
const msgs = await Session.messages({ sessionID: input.sessionID })
|
|
51
|
+
let total = 0
|
|
52
|
+
let pruned = 0
|
|
53
|
+
const toPrune = []
|
|
54
|
+
let turns = 0
|
|
55
|
+
|
|
56
|
+
loop: for (let msgIndex = msgs.length - 1; msgIndex >= 0; msgIndex--) {
|
|
57
|
+
const msg = msgs[msgIndex]
|
|
58
|
+
if (msg.info.role === "user") turns++
|
|
59
|
+
if (turns < 2) continue
|
|
60
|
+
if (msg.info.role === "assistant" && msg.info.summary) break loop
|
|
61
|
+
for (let partIndex = msg.parts.length - 1; partIndex >= 0; partIndex--) {
|
|
62
|
+
const part = msg.parts[partIndex]
|
|
63
|
+
if (part.type === "tool")
|
|
64
|
+
if (part.state.status === "completed") {
|
|
65
|
+
if (part.state.time.compacted) break loop
|
|
66
|
+
const estimate = Token.estimate(part.state.output)
|
|
67
|
+
total += estimate
|
|
68
|
+
if (total > PRUNE_PROTECT) {
|
|
69
|
+
pruned += estimate
|
|
70
|
+
toPrune.push(part)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
log.info("found", { pruned, total })
|
|
76
|
+
if (pruned > PRUNE_MINIMUM) {
|
|
77
|
+
for (const part of toPrune) {
|
|
78
|
+
if (part.state.status === "completed") {
|
|
79
|
+
part.state.time.compacted = Date.now()
|
|
80
|
+
await Session.updatePart(part)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
log.info("pruned", { count: toPrune.length })
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function process(input: {
|
|
88
|
+
parentID: string
|
|
89
|
+
messages: MessageV2.WithParts[]
|
|
90
|
+
sessionID: string
|
|
91
|
+
model: {
|
|
92
|
+
providerID: string
|
|
93
|
+
modelID: string
|
|
94
|
+
}
|
|
95
|
+
abort: AbortSignal
|
|
96
|
+
}) {
|
|
97
|
+
const model = await Provider.getModel(input.model.providerID, input.model.modelID)
|
|
98
|
+
const system = [...SystemPrompt.summarize(model.providerID)]
|
|
99
|
+
const msg = (await Session.updateMessage({
|
|
100
|
+
id: Identifier.ascending("message"),
|
|
101
|
+
role: "assistant",
|
|
102
|
+
parentID: input.parentID,
|
|
103
|
+
sessionID: input.sessionID,
|
|
104
|
+
mode: "build",
|
|
105
|
+
summary: true,
|
|
106
|
+
path: {
|
|
107
|
+
cwd: Instance.directory,
|
|
108
|
+
root: Instance.worktree,
|
|
109
|
+
},
|
|
110
|
+
cost: 0,
|
|
111
|
+
tokens: {
|
|
112
|
+
output: 0,
|
|
113
|
+
input: 0,
|
|
114
|
+
reasoning: 0,
|
|
115
|
+
cache: { read: 0, write: 0 },
|
|
116
|
+
},
|
|
117
|
+
modelID: input.model.modelID,
|
|
118
|
+
providerID: model.providerID,
|
|
119
|
+
time: {
|
|
120
|
+
created: Date.now(),
|
|
121
|
+
},
|
|
122
|
+
})) as MessageV2.Assistant
|
|
123
|
+
const processor = SessionProcessor.create({
|
|
124
|
+
assistantMessage: msg,
|
|
125
|
+
sessionID: input.sessionID,
|
|
126
|
+
providerID: input.model.providerID,
|
|
127
|
+
model: model.info,
|
|
128
|
+
abort: input.abort,
|
|
129
|
+
})
|
|
130
|
+
const result = await processor.process(() =>
|
|
131
|
+
streamText({
|
|
132
|
+
onError(error) {
|
|
133
|
+
log.error("stream error", {
|
|
134
|
+
error,
|
|
135
|
+
})
|
|
136
|
+
},
|
|
137
|
+
// set to 0, we handle loop
|
|
138
|
+
maxRetries: 0,
|
|
139
|
+
providerOptions: ProviderTransform.providerOptions(model.npm, model.providerID, {
|
|
140
|
+
...ProviderTransform.options(model.providerID, model.modelID, model.npm ?? "", input.sessionID),
|
|
141
|
+
...model.info.options,
|
|
142
|
+
}),
|
|
143
|
+
headers: model.info.headers,
|
|
144
|
+
abortSignal: input.abort,
|
|
145
|
+
tools: model.info.tool_call ? {} : undefined,
|
|
146
|
+
messages: [
|
|
147
|
+
...system.map(
|
|
148
|
+
(x): ModelMessage => ({
|
|
149
|
+
role: "system",
|
|
150
|
+
content: x,
|
|
151
|
+
}),
|
|
152
|
+
),
|
|
153
|
+
...MessageV2.toModelMessage(
|
|
154
|
+
input.messages.filter((m) => {
|
|
155
|
+
if (m.info.role !== "assistant" || m.info.error === undefined) {
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
if (
|
|
159
|
+
MessageV2.AbortedError.isInstance(m.info.error) &&
|
|
160
|
+
m.parts.some((part) => part.type !== "step-start" && part.type !== "reasoning")
|
|
161
|
+
) {
|
|
162
|
+
return true
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return false
|
|
166
|
+
}),
|
|
167
|
+
),
|
|
168
|
+
{
|
|
169
|
+
role: "user",
|
|
170
|
+
content: [
|
|
171
|
+
{
|
|
172
|
+
type: "text",
|
|
173
|
+
text: "Provide a detailed but concise summary of our conversation above. Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next.",
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
model: wrapLanguageModel({
|
|
179
|
+
model: model.language,
|
|
180
|
+
middleware: [
|
|
181
|
+
{
|
|
182
|
+
async transformParams(args) {
|
|
183
|
+
if (args.type === "stream") {
|
|
184
|
+
// @ts-expect-error
|
|
185
|
+
args.params.prompt = ProviderTransform.message(args.params.prompt, model.providerID, model.modelID)
|
|
186
|
+
}
|
|
187
|
+
return args.params
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
}),
|
|
192
|
+
}),
|
|
193
|
+
)
|
|
194
|
+
if (result === "continue") {
|
|
195
|
+
const continueMsg = await Session.updateMessage({
|
|
196
|
+
id: Identifier.ascending("message"),
|
|
197
|
+
role: "user",
|
|
198
|
+
sessionID: input.sessionID,
|
|
199
|
+
time: {
|
|
200
|
+
created: Date.now(),
|
|
201
|
+
},
|
|
202
|
+
agent: "build",
|
|
203
|
+
model: input.model,
|
|
204
|
+
})
|
|
205
|
+
await Session.updatePart({
|
|
206
|
+
id: Identifier.ascending("part"),
|
|
207
|
+
messageID: continueMsg.id,
|
|
208
|
+
sessionID: input.sessionID,
|
|
209
|
+
type: "text",
|
|
210
|
+
synthetic: true,
|
|
211
|
+
text: "Continue if you have next steps",
|
|
212
|
+
time: {
|
|
213
|
+
start: Date.now(),
|
|
214
|
+
end: Date.now(),
|
|
215
|
+
},
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
if (processor.message.error) return "stop"
|
|
219
|
+
return "continue"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const create = fn(
|
|
223
|
+
z.object({
|
|
224
|
+
sessionID: Identifier.schema("session"),
|
|
225
|
+
model: z.object({
|
|
226
|
+
providerID: z.string(),
|
|
227
|
+
modelID: z.string(),
|
|
228
|
+
}),
|
|
229
|
+
}),
|
|
230
|
+
async (input) => {
|
|
231
|
+
const msg = await Session.updateMessage({
|
|
232
|
+
id: Identifier.ascending("message"),
|
|
233
|
+
role: "user",
|
|
234
|
+
model: input.model,
|
|
235
|
+
sessionID: input.sessionID,
|
|
236
|
+
agent: "build",
|
|
237
|
+
time: {
|
|
238
|
+
created: Date.now(),
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
await Session.updatePart({
|
|
242
|
+
id: Identifier.ascending("part"),
|
|
243
|
+
messageID: msg.id,
|
|
244
|
+
sessionID: msg.sessionID,
|
|
245
|
+
type: "compaction",
|
|
246
|
+
})
|
|
247
|
+
},
|
|
248
|
+
)
|
|
249
|
+
}
|