Merge remote-tracking branch 'origin/v2' into search-integration

# Conflicts:
#	packages/client/test/promise.test.ts
#	packages/core/schema.json
#	packages/core/src/database/migration.gen.ts
#	packages/core/src/tool/websearch.ts
#	packages/sdk-next/src/index.ts
#	packages/sdk/js/src/v2/gen/types.gen.ts
This commit is contained in:
Shoubhit Dash 2026-07-07 17:38:46 +05:30
commit 7b8d8b8861
666 changed files with 46671 additions and 20220 deletions

View file

@ -19,37 +19,3 @@ export const Synced = Schema.Struct({
"Marker emitted once when a log read reaches its captured watermark. The reader holds every event committed at or below seq.",
})
export interface Synced extends Schema.Schema.Type<typeof Synced> {}
/**
* A payload-free doorbell: the aggregate's log advanced to at least `seq`.
* Hints are a latency optimization only; no consumer may derive correctness
* from receiving one. Correctness always comes from a durable log read plus
* the consumer's own checkpoint.
*/
export const Hint = Schema.Struct({
type: Schema.Literal("log.hint"),
aggregateID: Schema.String,
seq: Event.Seq,
}).annotate({
identifier: "EventLog.Hint",
description:
"Payload-free change hint: the aggregate's durable log advanced to at least seq. Hints coalesce under backpressure (latest per aggregate) and are never a delivery guarantee.",
})
export interface Hint extends Schema.Schema.Type<typeof Hint> {}
/**
* Hints may have been lost. Treat every aggregate as potentially dirty and
* recover via bounded sweep plus durable log reads. Also emitted first on
* every (re)subscribe, since hints during disconnection were never buffered.
*/
export const SweepRequired = Schema.Struct({
type: Schema.Literal("log.sweep_required"),
}).annotate({
identifier: "EventLog.SweepRequired",
description:
"Hints may have been lost; treat every aggregate as potentially dirty and recover via bounded sweep plus durable log reads. Emitted first on every (re)subscribe.",
})
export interface SweepRequired extends Schema.Schema.Type<typeof SweepRequired> {}
export const Change = Schema.Union([Hint, SweepRequired]).annotate({ identifier: "EventLog.Change" })
export type Change = typeof Change.Type

View file

@ -14,7 +14,7 @@ export type ID = typeof ID.Type
/**
* Position in one aggregate's durable log. Values originate from the durable
* event envelope, synced markers, change hints, and snapshot watermarks;
* event envelope and synced markers;
* `after` cursors accept only values that came from those sources.
*/
export const Seq = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.brand("Event.Seq"))

View file

@ -21,6 +21,7 @@ export { Revert } from "./revert.js"
export { Session } from "./session.js"
export { Vcs } from "./vcs.js"
export { SessionInput } from "./session-input.js"
export { SessionError } from "./session-error.js"
export { SessionMessage } from "./session-message.js"
export { Shell } from "./shell.js"
export { Skill } from "./skill.js"
@ -28,6 +29,6 @@ export { Pty } from "./pty.js"
export { PtyTicket } from "./pty-ticket.js"
export { Question } from "./question.js"
export { Workspace } from "./workspace.js"
export { Prompt, Source, FileAttachment, AgentAttachment } from "./prompt.js"
export { Prompt, PromptMention, FileSource, FileAttachment, AgentAttachment } from "./prompt.js"
export { PromptInput } from "./prompt-input.js"
export * from "./schema.js"

View file

@ -0,0 +1,20 @@
export * as InstructionEntry from "./instruction-entry.js"
import { Schema } from "effect"
/**
* Slash-free client-facing key for one API-managed instruction entry. The server
* derives the namespaced Instructions key as `api/<key>`, keeping the
* `api/*` namespace enforced by construction.
*/
export const Key = Schema.String.check(Schema.isPattern(/^[a-z0-9][a-z0-9._-]*$/)).annotate({
identifier: "InstructionEntry.Key",
description: "Instruction entry key (lowercase alphanumerics plus . _ -)",
})
export type Key = typeof Key.Type
export const Info = Schema.Struct({
key: Key,
value: Schema.Json.annotate({ description: "JSON value attached to the session's instructions" }),
}).annotate({ identifier: "InstructionEntry.Info" })
export interface Info extends Schema.Schema.Type<typeof Info> {}

View file

@ -8,6 +8,9 @@ export const ProviderMetadata = Schema.Record(Schema.String, Schema.Record(Schem
})
export type ProviderMetadata = Schema.Schema.Type<typeof ProviderMetadata>
export const FinishReason = Schema.Literals(["stop", "length", "tool-calls", "content-filter", "error", "unknown"])
export type FinishReason = typeof FinishReason.Type
export interface ToolTextContent extends Schema.Schema.Type<typeof ToolTextContent> {}
export const ToolTextContent = Schema.Struct({
type: Schema.Literal("text"),

View file

@ -1,9 +1,8 @@
export * as Model from "./model.js"
import { Schema } from "effect"
import { optional } from "./schema.js"
import { optional, statics } from "./schema.js"
import { Provider } from "./provider.js"
import { statics } from "./schema.js"
export const ID = Schema.String.pipe(Schema.brand("ModelV2.ID"))
export type ID = typeof ID.Type
@ -42,36 +41,23 @@ export const Cost = Schema.Struct({
}),
}).annotate({ identifier: "Model.Cost" })
export const Api = Schema.Union([
Schema.Struct({
id: ID,
...Provider.AISDK.fields,
}),
Schema.Struct({
id: ID,
...Provider.Native.fields,
}),
])
.pipe(Schema.toTaggedUnion("type"))
.annotate({ identifier: "Model.Api" })
export type Api = typeof Api.Type
export interface Variant extends Schema.Schema.Type<typeof Variant> {}
export const Variant = Schema.Struct({
id: VariantID,
...Provider.Overlays,
}).annotate({ identifier: "Model.Variant" })
export interface Info extends Schema.Schema.Type<typeof Info> {}
export const Info = Schema.Struct({
id: ID,
modelID: ID,
providerID: Provider.ID,
family: Family.pipe(optional),
name: Schema.String,
api: Api,
package: Provider.Package.pipe(optional),
...Provider.Overlays,
capabilities: Capabilities,
request: Schema.Struct({
...Provider.Request.fields,
variant: Schema.String.pipe(optional),
}),
variants: Schema.Struct({
id: VariantID,
...Provider.Request.fields,
}).pipe(Schema.Array),
variants: Schema.Array(Variant),
time: Schema.Struct({
released: Schema.Finite,
}),
@ -87,14 +73,13 @@ export const Info = Schema.Struct({
.annotate({ identifier: "ModelV2.Info" })
.pipe(
statics((schema) => ({
empty: (providerID: Provider.ID, modelID: ID) =>
empty: (providerID: Provider.ID, id: ID) =>
schema.make({
id: modelID,
id,
modelID: id,
providerID,
name: modelID,
api: { id: modelID, type: "native", settings: {} },
name: id,
capabilities: { tools: false, input: [], output: [] },
request: { settings: {}, headers: {}, body: {} },
variants: [],
time: { released: 0 },
cost: [],

View file

@ -1,7 +1,7 @@
export * as PromptInput from "./prompt-input.js"
import { Schema } from "effect"
import { AgentAttachment, Source } from "./prompt.js"
import { AgentAttachment, PromptMention } from "./prompt.js"
import { optional, statics } from "./schema.js"
export interface FileAttachment extends Schema.Schema.Type<typeof FileAttachment> {}
@ -9,7 +9,7 @@ export const FileAttachment = Schema.Struct({
uri: Schema.String,
name: Schema.String.pipe(optional),
description: Schema.String.pipe(optional),
source: Source.pipe(optional),
mention: PromptMention.pipe(optional),
})
.annotate({ identifier: "PromptInput.FileAttachment" })
.pipe(

View file

@ -2,31 +2,46 @@ import { Schema } from "effect"
import { optional } from "./schema.js"
import { statics } from "./schema.js"
export interface Source extends Schema.Schema.Type<typeof Source> {}
export const Source = Schema.Struct({
export interface PromptMention extends Schema.Schema.Type<typeof PromptMention> {}
export const PromptMention = Schema.Struct({
start: Schema.Finite,
end: Schema.Finite,
text: Schema.String,
}).annotate({ identifier: "Prompt.Source" })
}).annotate({ identifier: "Prompt.Mention" })
export const FileSource = Schema.Union([
Schema.Struct({ type: Schema.Literal("inline") }),
Schema.Struct({ type: Schema.Literal("uri"), uri: Schema.String }),
])
.pipe(Schema.toTaggedUnion("type"))
.annotate({ identifier: "Prompt.FileSource" })
export type FileSource = typeof FileSource.Type
export const Base64 = Schema.String.check(
Schema.isPattern(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
).annotate({ identifier: "Prompt.Base64" })
export type Base64 = typeof Base64.Type
export interface FileAttachment extends Schema.Schema.Type<typeof FileAttachment> {}
export const FileAttachment = Schema.Struct({
uri: Schema.String,
data: Base64,
mime: Schema.String,
source: FileSource,
name: Schema.String.pipe(optional),
description: Schema.String.pipe(optional),
source: Source.pipe(optional),
mention: PromptMention.pipe(optional),
})
.annotate({ identifier: "Prompt.FileAttachment" })
.pipe(
statics((schema) => ({
create: (input: FileAttachment) =>
schema.make({
uri: input.uri,
data: input.data,
mime: input.mime,
source: input.source,
name: input.name,
description: input.description,
source: input.source,
mention: input.mention,
}),
})),
)
@ -34,7 +49,7 @@ export const FileAttachment = Schema.Struct({
export interface AgentAttachment extends Schema.Schema.Type<typeof AgentAttachment> {}
export const AgentAttachment = Schema.Struct({
name: Schema.String,
source: Source.pipe(optional),
mention: PromptMention.pipe(optional),
}).annotate({ identifier: "Prompt.AgentAttachment" })
export interface Prompt extends Schema.Schema.Type<typeof Prompt> {}

View file

@ -1,9 +1,8 @@
export * as Provider from "./provider.js"
import { Effect, Schema } from "effect"
import { optional } from "./schema.js"
import { Integration } from "./integration.js"
import { statics } from "./schema.js"
import { optional, statics } from "./schema.js"
export const ID = Schema.String.pipe(
Schema.brand("ProviderV2.ID"),
@ -23,27 +22,16 @@ export const ID = Schema.String.pipe(
)
export type ID = typeof ID.Type
export interface AISDK extends Schema.Schema.Type<typeof AISDK> {}
export const AISDK = Schema.Struct({
type: Schema.Literal("aisdk"),
package: Schema.String,
url: Schema.String.pipe(optional),
settings: Schema.Record(Schema.String, Schema.Unknown).pipe(optional),
}).annotate({ identifier: "Provider.AISDK" })
export const Package = Schema.String
export type Package = typeof Package.Type
export interface Native extends Schema.Schema.Type<typeof Native> {}
export const Native = Schema.Struct({
type: Schema.Literal("native"),
url: Schema.String.pipe(optional),
settings: Schema.Record(Schema.String, Schema.Unknown),
}).annotate({ identifier: "Provider.Native" })
export const Overlays = {
settings: Schema.Record(Schema.String, Schema.Json).pipe(optional),
headers: Schema.Record(Schema.String, Schema.String).pipe(optional),
body: Schema.Record(Schema.String, Schema.Json).pipe(optional),
}
export const Api = Schema.Union([AISDK, Native])
.pipe(Schema.toTaggedUnion("type"))
.annotate({ identifier: "Provider.Api" })
export type Api = typeof Api.Type
export const Settings = Schema.Record(Schema.String, Schema.Unknown).annotate({ identifier: "Provider.Settings" })
export const Settings = Schema.Record(Schema.String, Schema.Json).annotate({ identifier: "Provider.Settings" })
export type Settings = typeof Settings.Type
export interface Request extends Schema.Schema.Type<typeof Request> {}
@ -59,18 +47,12 @@ export const Info = Schema.Struct({
integrationID: Integration.ID.pipe(optional),
name: Schema.String,
disabled: Schema.Boolean.pipe(optional),
api: Api,
request: Request,
package: Package,
...Overlays,
})
.annotate({ identifier: "ProviderV2.Info" })
.pipe(
statics((schema) => ({
empty: (id: ID) =>
schema.make({
id,
name: id,
api: { type: "native", settings: {} },
request: { settings: {}, headers: {}, body: {} },
}),
empty: (id: ID) => schema.make({ id, name: id, package: "" }),
})),
)

View file

@ -1,20 +0,0 @@
export * as SessionContextEntry from "./session-context-entry.js"
import { Schema } from "effect"
/**
* Slash-free client-facing key for one API-managed context entry. The server
* derives the namespaced SystemContext key as `api/<key>`, keeping the
* `api/*` namespace enforced by construction.
*/
export const Key = Schema.String.check(Schema.isPattern(/^[a-z0-9][a-z0-9._-]*$/)).annotate({
identifier: "SessionContextEntry.Key",
description: "Context entry key (lowercase alphanumerics plus . _ -)",
})
export type Key = typeof Key.Type
export const Info = Schema.Struct({
key: Key,
value: Schema.Json.annotate({ description: "JSON value attached to the session's system context" }),
}).annotate({ identifier: "SessionContextEntry.Info" })
export interface Info extends Schema.Schema.Type<typeof Info> {}

View file

@ -0,0 +1,9 @@
export * as SessionError from "./session-error.js"
import { Schema } from "effect"
export interface Error extends Schema.Schema.Type<typeof Error> {}
export const Error = Schema.Struct({
type: Schema.String,
message: Schema.String,
}).annotate({ identifier: "Session.StructuredError" })

View file

@ -3,16 +3,18 @@ export * as SessionEvent from "./session-event.js"
import { Schema } from "effect"
import { optional } from "./schema.js"
import { Event } from "./event.js"
import { ProviderMetadata, ToolContent } from "./llm.js"
import { ToolContent } from "./llm.js"
import { FinishReason } from "./llm.js"
import { Delivery } from "./session-delivery.js"
import { Model } from "./model.js"
import { NonNegativeInt, RelativePath } from "./schema.js"
import { NonNegativeInt, PositiveInt, RelativePath } from "./schema.js"
import { FileAttachment, Prompt } from "./prompt.js"
import { SessionID } from "./session-id.js"
import { Location } from "./location.js"
import { SessionMessage } from "./session-message.js"
import { Revert } from "./revert.js"
import { Shell as ShellSchema } from "./shell.js"
import { SessionError } from "./session-error.js"
export { FileAttachment }
@ -41,16 +43,6 @@ const options = {
version: 1,
},
} as const
const stepSettlementOptions = {
durable: {
aggregate: "sessionID",
version: 1,
},
} as const
export const UnknownError = SessionMessage.UnknownError
export type UnknownError = SessionMessage.UnknownError
export const AgentSelected = Event.durable({
type: "session.agent.selected",
...options,
@ -92,6 +84,16 @@ export const Renamed = Event.durable({
})
export type Renamed = typeof Renamed.Type
export const Deleted = Event.durable({
type: "session.deleted",
durable: {
aggregate: "sessionID",
version: 2,
},
schema: Base,
})
export type Deleted = typeof Deleted.Type
export const Forked = Event.durable({
type: "session.forked",
...options,
@ -120,25 +122,37 @@ export const PromptAdmitted = Event.durable({
})
export type PromptAdmitted = typeof PromptAdmitted.Type
export const ExecutionSettled = Event.ephemeral({
type: "session.execution.settled",
schema: {
...Base,
outcome: Schema.Literals(["success", "failure", "interrupted"]),
error: UnknownError.pipe(optional),
},
})
export type ExecutionSettled = typeof ExecutionSettled.Type
export namespace Execution {
export const Started = Event.durable({ type: "session.execution.started", ...options, schema: Base })
export type Started = typeof Started.Type
export const ContextUpdated = Event.durable({
type: "session.context.updated",
export const Succeeded = Event.durable({ type: "session.execution.succeeded", ...options, schema: Base })
export type Succeeded = typeof Succeeded.Type
export const Failed = Event.durable({
type: "session.execution.failed",
...options,
schema: { ...Base, error: SessionError.Error },
})
export type Failed = typeof Failed.Type
export const Interrupted = Event.durable({
type: "session.execution.interrupted",
...options,
schema: { ...Base, reason: Schema.Literals(["user", "shutdown", "superseded"]) },
})
export type Interrupted = typeof Interrupted.Type
}
export const InstructionsUpdated = Event.durable({
type: "session.instructions.updated",
...options,
schema: {
...Base,
text: Schema.String,
},
})
export type ContextUpdated = typeof ContextUpdated.Type
export type InstructionsUpdated = typeof InstructionsUpdated.Type
export const Synthetic = Event.durable({
type: "session.synthetic",
@ -204,11 +218,11 @@ export namespace Step {
export const Ended = Event.durable({
type: "session.step.ended",
...stepSettlementOptions,
...options,
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
finish: Schema.String,
finish: FinishReason,
cost: Schema.Finite,
tokens: Schema.Struct({
input: Schema.Finite,
@ -227,11 +241,11 @@ export namespace Step {
export const Failed = Event.durable({
type: "session.step.failed",
...stepSettlementOptions,
...options,
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
error: UnknownError,
error: SessionError.Error,
},
})
export type Failed = typeof Failed.Type
@ -244,7 +258,7 @@ export namespace Text {
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
textID: Schema.String,
ordinal: NonNegativeInt,
},
})
export type Started = typeof Started.Type
@ -255,7 +269,7 @@ export namespace Text {
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
textID: Schema.String,
ordinal: NonNegativeInt,
delta: Schema.String,
},
})
@ -267,7 +281,7 @@ export namespace Text {
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
textID: Schema.String,
ordinal: NonNegativeInt,
text: Schema.String,
},
})
@ -281,8 +295,8 @@ export namespace Reasoning {
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
reasoningID: Schema.String,
providerMetadata: ProviderMetadata.pipe(optional),
ordinal: NonNegativeInt,
state: SessionMessage.ProviderState.pipe(optional),
},
})
export type Started = typeof Started.Type
@ -293,7 +307,7 @@ export namespace Reasoning {
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
reasoningID: Schema.String,
ordinal: NonNegativeInt,
delta: Schema.String,
},
})
@ -305,9 +319,9 @@ export namespace Reasoning {
schema: {
...Base,
assistantMessageID: SessionMessage.ID,
reasoningID: Schema.String,
ordinal: NonNegativeInt,
text: Schema.String,
providerMetadata: ProviderMetadata.pipe(optional),
state: SessionMessage.ProviderState.pipe(optional),
},
})
export type Ended = typeof Ended.Type
@ -357,12 +371,9 @@ export namespace Tool {
...options,
schema: {
...ToolBase,
tool: Schema.String,
input: Schema.Record(Schema.String, Schema.Unknown),
provider: Schema.Struct({
executed: Schema.Boolean,
metadata: ProviderMetadata.pipe(optional),
}),
executed: Schema.Boolean,
state: SessionMessage.ProviderState.pipe(optional),
},
})
export type Called = typeof Called.Type
@ -391,10 +402,8 @@ export namespace Tool {
content: Schema.Array(ToolContent),
outputPaths: Schema.Array(Schema.String).pipe(optional),
result: Schema.Unknown.pipe(optional),
provider: Schema.Struct({
executed: Schema.Boolean,
metadata: ProviderMetadata.pipe(optional),
}),
executed: Schema.Boolean,
resultState: SessionMessage.ProviderState.pipe(optional),
},
})
export type Success = typeof Success.Type
@ -404,41 +413,39 @@ export namespace Tool {
...options,
schema: {
...ToolBase,
error: UnknownError,
error: SessionError.Error,
result: Schema.Unknown.pipe(optional),
provider: Schema.Struct({
executed: Schema.Boolean,
metadata: ProviderMetadata.pipe(optional),
}),
executed: Schema.Boolean,
resultState: SessionMessage.ProviderState.pipe(optional),
},
})
export type Failed = typeof Failed.Type
}
export const RetryError = Schema.Struct({
message: Schema.String,
statusCode: Schema.Finite.pipe(optional),
isRetryable: Schema.Boolean,
responseHeaders: Schema.Record(Schema.String, Schema.String).pipe(optional),
responseBody: Schema.String.pipe(optional),
metadata: Schema.Record(Schema.String, Schema.String).pipe(optional),
}).annotate({
identifier: "session.retry.error",
})
export interface RetryError extends Schema.Schema.Type<typeof RetryError> {}
export const Retried = Event.durable({
type: "session.retried",
export const RetryScheduled = Event.durable({
type: "session.retry.scheduled",
...options,
schema: {
...Base,
attempt: Schema.Finite,
error: RetryError,
assistantMessageID: SessionMessage.ID,
attempt: PositiveInt,
at: NonNegativeInt,
error: SessionError.Error,
},
})
export type Retried = typeof Retried.Type
export type RetryScheduled = typeof RetryScheduled.Type
export namespace Compaction {
export const Admitted = Event.durable({
type: "session.compaction.admitted",
...options,
schema: {
...Base,
inputID: SessionMessage.ID,
},
})
export type Admitted = typeof Admitted.Type
export const Started = Event.durable({
type: "session.compaction.started",
...options,
@ -469,6 +476,13 @@ export namespace Compaction {
},
})
export type Ended = typeof Ended.Type
export const Failed = Event.durable({
type: "session.compaction.failed",
...options,
schema: Base,
})
export type Failed = typeof Failed.Type
}
export namespace RevertEvent {
@ -481,7 +495,7 @@ export namespace RevertEvent {
export const Committed = Event.durable({
type: "session.revert.committed",
...options,
schema: { ...Base, messageID: SessionMessage.ID },
schema: { ...Base, to: SessionMessage.ID },
})
}
@ -490,11 +504,15 @@ export const Definitions = Event.inventory(
ModelSelected,
Moved,
Renamed,
Deleted,
Forked,
PromptPromoted,
PromptAdmitted,
ExecutionSettled,
ContextUpdated,
Execution.Started,
Execution.Succeeded,
Execution.Failed,
Execution.Interrupted,
InstructionsUpdated,
Synthetic,
Skill.Activated,
Shell.Started,
@ -515,10 +533,12 @@ export const Definitions = Event.inventory(
Tool.Progress,
Tool.Success,
Tool.Failed,
Retried,
RetryScheduled,
Compaction.Admitted,
Compaction.Started,
Compaction.Delta,
Compaction.Ended,
Compaction.Failed,
RevertEvent.Staged,
RevertEvent.Cleared,
RevertEvent.Committed,

View file

@ -21,3 +21,22 @@ export const Admitted = Schema.Struct({
timeCreated: DateTimeUtcFromMillis,
promotedSeq: NonNegativeInt.pipe(optional),
}).annotate({ identifier: "SessionInput.Admitted" })
export interface PromptEntry extends Schema.Schema.Type<typeof PromptEntry> {}
export const PromptEntry = Schema.Struct({
type: Schema.Literal("prompt"),
...Admitted.fields,
}).annotate({ identifier: "SessionInput.PromptEntry" })
export interface Compaction extends Schema.Schema.Type<typeof Compaction> {}
export const Compaction = Schema.Struct({
type: Schema.Literal("compaction"),
admittedSeq: NonNegativeInt,
id: SessionMessage.ID,
sessionID: SessionID,
timeCreated: DateTimeUtcFromMillis,
handledSeq: NonNegativeInt.pipe(optional),
}).annotate({ identifier: "SessionInput.Compaction" })
export const Entry = Schema.Union([PromptEntry, Compaction]).pipe(Schema.toTaggedUnion("type"))
export type Entry = typeof Entry.Type

View file

@ -2,14 +2,16 @@ export * as SessionMessage from "./session-message.js"
import { Schema } from "effect"
import { optional } from "./schema.js"
import { ProviderMetadata, ToolContent } from "./llm.js"
import { ToolContent } from "./llm.js"
import { Model } from "./model.js"
import { FileAttachment, Prompt } from "./prompt.js"
import { DateTimeUtcFromMillis, RelativePath, statics } from "./schema.js"
import { DateTimeUtcFromMillis, PositiveInt, RelativePath, statics } from "./schema.js"
import { SessionID } from "./session-id.js"
import { ascending } from "./identifier.js"
import { Event } from "./event.js"
import { Shell as ShellSchema } from "./shell.js"
import { FinishReason } from "./llm.js"
import { SessionError } from "./session-error.js"
export const ID = Schema.String.check(Schema.isStartsWith("msg_")).pipe(
Schema.brand("Session.Message.ID"),
@ -20,18 +22,17 @@ export const ID = Schema.String.check(Schema.isStartsWith("msg_")).pipe(
)
export type ID = typeof ID.Type
export interface UnknownError extends Schema.Schema.Type<typeof UnknownError> {}
export const UnknownError = Schema.Struct({
type: Schema.Literal("unknown"),
message: Schema.String,
}).annotate({ identifier: "Session.Error.Unknown" })
const Base = {
id: ID,
metadata: Schema.Record(Schema.String, Schema.Unknown).pipe(optional),
time: Schema.Struct({ created: DateTimeUtcFromMillis }),
}
export const ProviderState = Schema.Record(Schema.String, Schema.Unknown).annotate({
identifier: "Session.Message.ProviderState",
})
export type ProviderState = typeof ProviderState.Type
export interface AgentSelected extends Schema.Schema.Type<typeof AgentSelected> {}
export const AgentSelected = Schema.Struct({
...Base,
@ -123,7 +124,7 @@ export const ToolStateError = Schema.Struct({
input: Schema.Record(Schema.String, Schema.Unknown),
content: ToolContent.pipe(Schema.Array),
structured: Schema.Record(Schema.String, Schema.Unknown),
error: UnknownError,
error: SessionError.Error,
result: Schema.Unknown.pipe(optional),
}).annotate({ identifier: "Session.Message.ToolState.Error" })
@ -137,11 +138,9 @@ export const AssistantTool = Schema.Struct({
type: Schema.Literal("tool"),
id: Schema.String,
name: Schema.String,
provider: Schema.Struct({
executed: Schema.Boolean,
metadata: ProviderMetadata.pipe(optional),
resultMetadata: ProviderMetadata.pipe(optional),
}).pipe(optional),
executed: Schema.Boolean.pipe(optional),
providerState: ProviderState.pipe(optional),
providerResultState: ProviderState.pipe(optional),
state: ToolState,
time: Schema.Struct({
created: DateTimeUtcFromMillis,
@ -154,16 +153,14 @@ export const AssistantTool = Schema.Struct({
export interface AssistantText extends Schema.Schema.Type<typeof AssistantText> {}
export const AssistantText = Schema.Struct({
type: Schema.Literal("text"),
id: Schema.String,
text: Schema.String,
}).annotate({ identifier: "Session.Message.Assistant.Text" })
export interface AssistantReasoning extends Schema.Schema.Type<typeof AssistantReasoning> {}
export const AssistantReasoning = Schema.Struct({
type: Schema.Literal("reasoning"),
id: Schema.String,
text: Schema.String,
providerMetadata: ProviderMetadata.pipe(optional),
state: ProviderState.pipe(optional),
time: Schema.Struct({
created: DateTimeUtcFromMillis,
completed: DateTimeUtcFromMillis.pipe(optional),
@ -175,6 +172,13 @@ export const AssistantContent = Schema.Union([AssistantText, AssistantReasoning,
)
export type AssistantContent = AssistantText | AssistantReasoning | AssistantTool
export interface AssistantRetry extends Schema.Schema.Type<typeof AssistantRetry> {}
export const AssistantRetry = Schema.Struct({
attempt: PositiveInt,
at: DateTimeUtcFromMillis,
error: SessionError.Error,
}).annotate({ identifier: "Session.Message.Assistant.Retry" })
export interface Assistant extends Schema.Schema.Type<typeof Assistant> {}
export const Assistant = Schema.Struct({
...Base,
@ -187,7 +191,7 @@ export const Assistant = Schema.Struct({
end: Schema.String.pipe(optional),
files: Schema.Array(RelativePath).pipe(optional),
}).pipe(optional),
finish: Schema.String.pipe(optional),
finish: FinishReason.pipe(optional),
cost: Schema.Finite.pipe(optional),
tokens: Schema.Struct({
input: Schema.Finite,
@ -195,7 +199,8 @@ export const Assistant = Schema.Struct({
reasoning: Schema.Finite,
cache: Schema.Struct({ read: Schema.Finite, write: Schema.Finite }),
}).pipe(optional),
error: UnknownError.pipe(optional),
error: SessionError.Error.pipe(optional),
retry: AssistantRetry.pipe(optional),
time: Schema.Struct({
created: DateTimeUtcFromMillis,
completed: DateTimeUtcFromMillis.pipe(optional),
@ -205,6 +210,7 @@ export const Assistant = Schema.Struct({
export interface Compaction extends Schema.Schema.Type<typeof Compaction> {}
export const Compaction = Schema.Struct({
type: Schema.Literal("compaction"),
status: Schema.Literals(["queued", "running", "completed", "failed"]),
reason: Schema.Literals(["auto", "manual"]),
summary: Schema.String,
recent: Schema.String,

View file

@ -8,6 +8,7 @@ import { Project } from "./project.js"
import { DateTimeUtcFromMillis, optional, RelativePath } from "./schema.js"
import { SessionEvent } from "./session-event.js"
import { SessionID } from "./session-id.js"
import { SessionMessage } from "./session-message.js"
import { Revert } from "./revert.js"
export const ID = SessionID
@ -19,6 +20,10 @@ export interface Info extends Schema.Schema.Type<typeof Info> {}
export const Info = Schema.Struct({
id: ID,
parentID: ID.pipe(optional),
fork: Schema.Struct({
sessionID: ID,
messageID: SessionMessage.ID.pipe(optional),
}).pipe(optional),
projectID: Project.ID,
agent: Agent.ID.pipe(optional),
model: Model.Ref.pipe(optional),

View file

@ -57,7 +57,7 @@ export const Event = { Created, Exited, Deleted, Definitions: inventory(Created,
export const CreateInput = Schema.Struct({
command: Schema.String,
cwd: optional(Schema.String),
timeout: optional(NonNegativeInt),
timeout: NonNegativeInt,
metadata: optional(Metadata),
})
export interface CreateInput extends Schema.Schema.Type<typeof CreateInput> {}