mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-30 05:42:09 +00:00
refactor(core): use nonempty array guards (#45718)
This commit is contained in:
parent
e409567428
commit
b1d7dd82fc
3 changed files with 10 additions and 23 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { type LLMEvent, type ProviderMetadata, type ToolResultValue } from "@opencode-ai/ai"
|
||||
import { Clock, Effect, Iterable } from "effect"
|
||||
import { isArrayNonEmpty, isReadonlyArrayNonEmpty } from "effect/Array"
|
||||
import { Bus } from "../../bus.js"
|
||||
import { Model } from "../../model.js"
|
||||
import { SessionEvent } from "../event.js"
|
||||
|
|
@ -45,9 +46,6 @@ export interface StepRecord {
|
|||
/** Derives canonical model content from a provider-hosted tool result. */
|
||||
type NonEmptyContent = readonly [Tool.Content, ...Tool.Content[]]
|
||||
|
||||
const nonEmpty = (content: ReadonlyArray<Tool.Content>): NonEmptyContent | undefined =>
|
||||
content.length > 0 ? (content as NonEmptyContent) : undefined
|
||||
|
||||
const stringify = (value: unknown) => {
|
||||
if (typeof value === "string") return value
|
||||
try {
|
||||
|
|
@ -58,10 +56,7 @@ const stringify = (value: unknown) => {
|
|||
}
|
||||
|
||||
const hostedContent = (result: ToolResultValue): NonEmptyContent => {
|
||||
if (result.type === "content") {
|
||||
const content = nonEmpty(result.value)
|
||||
if (content !== undefined) return content
|
||||
}
|
||||
if (result.type === "content" && isReadonlyArrayNonEmpty(result.value)) return result.value
|
||||
return [{ type: "text", text: stringify(result.value) }]
|
||||
}
|
||||
|
||||
|
|
@ -563,12 +558,12 @@ export const createLLMEventPublisher = (bus: Pick<Bus.Interface, "publish">, inp
|
|||
: result.content === undefined
|
||||
? []
|
||||
: [...result.content]
|
||||
if (content.length === 0) return yield* Effect.die(new Error(`Tool execution has no content: ${id}`))
|
||||
if (!isArrayNonEmpty(content)) return yield* Effect.die(new Error(`Tool execution has no content: ${id}`))
|
||||
yield* bus.publish(SessionEvent.Tool.Success, {
|
||||
sessionID: input.sessionID,
|
||||
assistantMessageID,
|
||||
id,
|
||||
content: [content[0], ...content.slice(1)],
|
||||
content,
|
||||
...(result.metadata === undefined ? {} : { metadata: result.metadata }),
|
||||
executed: tool.providerExecuted,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Tool } from "@opencode-ai/schema/tool"
|
|||
import { Skill } from "@opencode-ai/schema/skill"
|
||||
import { eq } from "drizzle-orm"
|
||||
import { Context, DateTime, Effect, Layer, Schema } from "effect"
|
||||
import { map } from "effect/Array"
|
||||
import path from "path"
|
||||
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
|
||||
import { App } from "../app.js"
|
||||
|
|
@ -309,21 +310,13 @@ function sanitizeToolState(id: string, state: SessionMessage.ToolState): Session
|
|||
return {
|
||||
...state,
|
||||
input: { redacted: `tool-input:${id}` },
|
||||
content: [
|
||||
sanitizeToolContent(id, state.content[0]),
|
||||
...state.content.slice(1).map((item) => sanitizeToolContent(id, item)),
|
||||
],
|
||||
content: map(state.content, (item) => sanitizeToolContent(id, item)),
|
||||
metadata: meta,
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
input: { redacted: `tool-input:${id}` },
|
||||
content: state.content
|
||||
? [
|
||||
sanitizeToolContent(id, state.content[0]),
|
||||
...state.content.slice(1).map((item) => sanitizeToolContent(id, item)),
|
||||
]
|
||||
: undefined,
|
||||
content: state.content ? map(state.content, (item) => sanitizeToolContent(id, item)) : undefined,
|
||||
metadata: meta,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { NonEmptyReadonlyArray } from "effect/Array"
|
||||
import { isArrayNonEmpty } from "effect/Array"
|
||||
import * as NodeSink from "@effect/platform-node/NodeSink"
|
||||
import * as NodeStream from "@effect/platform-node/NodeStream"
|
||||
import { Deferred, Effect, Exit, FileSystem, Layer, Path, PlatformError, Predicate, Sink, Stream } from "effect"
|
||||
|
|
@ -60,10 +60,9 @@ const flatten = (command: ChildProcess.Command) => {
|
|||
}
|
||||
|
||||
walk(command)
|
||||
if (commands.length === 0) throw new Error("flatten produced empty commands array")
|
||||
const [head, ...tail] = commands
|
||||
if (!isArrayNonEmpty(commands)) throw new Error("flatten produced empty commands array")
|
||||
return {
|
||||
commands: [head, ...tail] as NonEmptyReadonlyArray<ChildProcess.StandardCommand>,
|
||||
commands,
|
||||
opts,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue