Merge branch 'dev' into project
This commit is contained in:
@@ -10,7 +10,6 @@ import {
|
||||
type LanguageModelUsage,
|
||||
type ProviderMetadata,
|
||||
type ModelMessage,
|
||||
stepCountIs,
|
||||
type StreamTextResult,
|
||||
} from "ai"
|
||||
|
||||
@@ -42,6 +41,8 @@ import { Plugin } from "../plugin"
|
||||
import { Project } from "../project/project"
|
||||
import { Instance } from "../project/instance"
|
||||
import { Agent } from "../agent/agent"
|
||||
import { Permission } from "../permission"
|
||||
import { Wildcard } from "../util/wildcard"
|
||||
|
||||
export namespace Session {
|
||||
const log = Log.create({ service: "session" })
|
||||
@@ -525,6 +526,7 @@ export namespace Session {
|
||||
t.execute(args, {
|
||||
sessionID: input.sessionID,
|
||||
abort: new AbortController().signal,
|
||||
agent: input.agent!,
|
||||
messageID: userMsg.id,
|
||||
metadata: async () => {},
|
||||
}),
|
||||
@@ -611,15 +613,6 @@ export namespace Session {
|
||||
]
|
||||
}),
|
||||
).then((x) => x.flat())
|
||||
if (inputAgent === "plan")
|
||||
userParts.push({
|
||||
id: Identifier.ascending("part"),
|
||||
messageID: userMsg.id,
|
||||
sessionID: input.sessionID,
|
||||
type: "text",
|
||||
text: PROMPT_PLAN,
|
||||
synthetic: true,
|
||||
})
|
||||
await Plugin.trigger(
|
||||
"chat.message",
|
||||
{},
|
||||
@@ -682,7 +675,10 @@ export namespace Session {
|
||||
generateText({
|
||||
maxOutputTokens: small.info.reasoning ? 1024 : 20,
|
||||
providerOptions: {
|
||||
[input.providerID]: small.info.options,
|
||||
[input.providerID]: {
|
||||
...small.info.options,
|
||||
...ProviderTransform.options(input.providerID, small.info.id, input.sessionID),
|
||||
},
|
||||
},
|
||||
messages: [
|
||||
...SystemPrompt.title(input.providerID).map(
|
||||
@@ -719,6 +715,16 @@ export namespace Session {
|
||||
}
|
||||
|
||||
const agent = await Agent.get(inputAgent)
|
||||
if (agent.name === "plan") {
|
||||
msgs.at(-1)?.parts.push({
|
||||
id: Identifier.ascending("part"),
|
||||
messageID: userMsg.id,
|
||||
sessionID: input.sessionID,
|
||||
type: "text",
|
||||
text: PROMPT_PLAN,
|
||||
synthetic: true,
|
||||
})
|
||||
}
|
||||
let system = SystemPrompt.header(input.providerID)
|
||||
system.push(
|
||||
...(() => {
|
||||
@@ -763,11 +769,11 @@ export namespace Session {
|
||||
|
||||
const enabledTools = pipe(
|
||||
agent.tools,
|
||||
mergeDeep(await ToolRegistry.enabled(input.providerID, input.modelID)),
|
||||
mergeDeep(await ToolRegistry.enabled(input.providerID, input.modelID, agent)),
|
||||
mergeDeep(input.tools ?? {}),
|
||||
)
|
||||
for (const item of await ToolRegistry.tools(input.providerID, input.modelID)) {
|
||||
if (enabledTools[item.id] === false) continue
|
||||
if (Wildcard.all(item.id, enabledTools) === false) continue
|
||||
tools[item.id] = tool({
|
||||
id: item.id as any,
|
||||
description: item.description,
|
||||
@@ -789,6 +795,7 @@ export namespace Session {
|
||||
abort: options.abortSignal!,
|
||||
messageID: assistantMsg.id,
|
||||
callID: options.toolCallId,
|
||||
agent: agent.name,
|
||||
metadata: async (val) => {
|
||||
const match = processor.partFromToolCall(options.toolCallId)
|
||||
if (match && match.state.status === "running") {
|
||||
@@ -828,7 +835,7 @@ export namespace Session {
|
||||
}
|
||||
|
||||
for (const [key, item] of Object.entries(await MCP.tools())) {
|
||||
if (enabledTools[key] === false) continue
|
||||
if (Wildcard.all(key, enabledTools) === false) continue
|
||||
const execute = item.execute
|
||||
if (!execute) continue
|
||||
item.execute = async (args, opts) => {
|
||||
@@ -851,20 +858,24 @@ export namespace Session {
|
||||
tools[key] = item
|
||||
}
|
||||
|
||||
const params = {
|
||||
temperature: model.info.temperature
|
||||
? (agent.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID))
|
||||
: undefined,
|
||||
topP: agent.topP ?? ProviderTransform.topP(input.providerID, input.modelID),
|
||||
}
|
||||
await Plugin.trigger(
|
||||
const params = await Plugin.trigger(
|
||||
"chat.params",
|
||||
{
|
||||
model: model.info,
|
||||
provider: await Provider.getProvider(input.providerID),
|
||||
message: userMsg,
|
||||
},
|
||||
params,
|
||||
{
|
||||
temperature: model.info.temperature
|
||||
? (agent.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID))
|
||||
: undefined,
|
||||
topP: agent.topP ?? ProviderTransform.topP(input.providerID, input.modelID),
|
||||
options: {
|
||||
...ProviderTransform.options(input.providerID, input.modelID, input.sessionID),
|
||||
...model.info.options,
|
||||
...agent.options,
|
||||
},
|
||||
},
|
||||
)
|
||||
console.log(outputLimit)
|
||||
const stream = streamText({
|
||||
@@ -933,9 +944,20 @@ export namespace Session {
|
||||
activeTools: Object.keys(tools).filter((x) => x !== "invalid"),
|
||||
maxOutputTokens: outputLimit,
|
||||
abortSignal: abort.signal,
|
||||
stopWhen: stepCountIs(1000),
|
||||
stopWhen: async ({ steps }) => {
|
||||
if (steps.length >= 1000) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if processor flagged that we should stop
|
||||
if (processor.getShouldStop()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
providerOptions: {
|
||||
[input.providerID]: model.info.options,
|
||||
[input.providerID]: params.options,
|
||||
},
|
||||
temperature: params.temperature,
|
||||
topP: params.topP,
|
||||
@@ -981,13 +1003,18 @@ export namespace Session {
|
||||
function createProcessor(assistantMsg: MessageV2.Assistant, model: ModelsDev.Model) {
|
||||
const toolcalls: Record<string, MessageV2.ToolPart> = {}
|
||||
let snapshot: string | undefined
|
||||
let shouldStop = false
|
||||
return {
|
||||
partFromToolCall(toolCallID: string) {
|
||||
return toolcalls[toolCallID]
|
||||
},
|
||||
getShouldStop() {
|
||||
return shouldStop
|
||||
},
|
||||
async process(stream: StreamTextResult<Record<string, AITool>, never>) {
|
||||
try {
|
||||
let currentText: MessageV2.TextPart | undefined
|
||||
let reasoningMap: Record<string, MessageV2.ReasoningPart> = {}
|
||||
|
||||
for await (const value of stream.fullStream) {
|
||||
log.info("part", {
|
||||
@@ -997,6 +1024,44 @@ export namespace Session {
|
||||
case "start":
|
||||
break
|
||||
|
||||
case "reasoning-start":
|
||||
if (value.id in reasoningMap) {
|
||||
continue
|
||||
}
|
||||
reasoningMap[value.id] = {
|
||||
id: Identifier.ascending("part"),
|
||||
messageID: assistantMsg.id,
|
||||
sessionID: assistantMsg.sessionID,
|
||||
type: "reasoning",
|
||||
text: "",
|
||||
time: {
|
||||
start: Date.now(),
|
||||
},
|
||||
}
|
||||
break
|
||||
|
||||
case "reasoning-delta":
|
||||
if (value.id in reasoningMap) {
|
||||
const part = reasoningMap[value.id]
|
||||
part.text += value.text
|
||||
if (part.text) await updatePart(part)
|
||||
}
|
||||
break
|
||||
|
||||
case "reasoning-end":
|
||||
if (value.id in reasoningMap) {
|
||||
const part = reasoningMap[value.id]
|
||||
part.text = part.text.trimEnd()
|
||||
part.metadata = value.providerMetadata
|
||||
part.time = {
|
||||
...part.time,
|
||||
end: Date.now(),
|
||||
}
|
||||
await updatePart(part)
|
||||
delete reasoningMap[value.id]
|
||||
}
|
||||
break
|
||||
|
||||
case "tool-input-start":
|
||||
const part = await updatePart({
|
||||
id: toolcalls[value.id]?.id ?? Identifier.ascending("part"),
|
||||
@@ -1061,6 +1126,9 @@ export namespace Session {
|
||||
case "tool-error": {
|
||||
const match = toolcalls[value.toolCallId]
|
||||
if (match && match.state.status === "running") {
|
||||
if (value.error instanceof Permission.RejectedError) {
|
||||
shouldStop = true
|
||||
}
|
||||
await updatePart({
|
||||
...match,
|
||||
state: {
|
||||
@@ -1077,7 +1145,6 @@ export namespace Session {
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case "error":
|
||||
throw value.error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user