Skip to content

feat(core): add session metadata support#23068

Open
shantur wants to merge 3 commits into
anomalyco:devfrom
shantur:session-metadata
Open

feat(core): add session metadata support#23068
shantur wants to merge 3 commits into
anomalyco:devfrom
shantur:session-metadata

Conversation

@shantur
Copy link
Copy Markdown
Contributor

@shantur shantur commented Apr 17, 2026

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Introduces a metadata field in sessions that can be used with SDK to persist client controlled JSON metadata for session. This is simlar to metadata available in Message.Parts
Session APIs and SDK exposes metadata for create, get, update, list, and fork operations.

Support full metadata replacement on session update, add copyMetadata to session forks with default copy behavior,

If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!

How did you verify your code works?

Added tests and manual testing.

Screenshots / recordings

If this is a UI change, please include a screenshot or recording.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

If you do not follow this template your PR will be automatically rejected.

shantur added 2 commits May 11, 2026 18:41
Persist session metadata in the session store and expose it across the session APIs and SDK so clients can round-trip metadata during create, get, update, list, and fork operations.

Add a JSON metadata column to the session table, thread metadata through the session model/projectors, and normalize empty metadata responses to {}.

Support full metadata replacement on session update, add copyMetadata to session forks with default copy behavior, regenerate the session SDK surface, and cover the behavior with server/session tests plus a migration for existing databases.
@shantur shantur force-pushed the session-metadata branch from 8c06b4f to c3351cb Compare May 11, 2026 18:09
@rekram1-node
Copy link
Copy Markdown
Collaborator

/review

@@ -33,6 +33,7 @@ export const SessionTable = sqliteTable(
summary_deletions: integer(),
summary_files: integer(),
summary_diffs: text({ mode: "json" }).$type<Snapshot.FileDiff[]>(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion (style): this new metadata type uses any, which the repo style guide asks us to avoid. Since this is client-controlled JSON and the generated SDK exposes unknown, consider carrying Record<string, unknown> through the storage/service types instead of Record<string, any>.

export type SessionUpdateData = {
body?: {
title?: string
metadata?: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: the update route accepts metadata: null to clear metadata, but the generated SDK type only allows an object here. That means SDK callers cannot type-safely use the clear path covered by the API/tests. Since this file is generated, the source fix may need to make the nullable schema survive generation so this becomes { [key: string]: unknown } | null.

# Conflicts:
#	packages/opencode/src/session/session.ts
@rekram1-node
Copy link
Copy Markdown
Collaborator

/review

const Metadata = Schema.Record(Schema.String, Schema.Any)

export const Info = Schema.Struct({
id: SessionID,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion for the human to consider: this new field introduces any, which is avoidable here and the PR describes this as JSON metadata. Using a JSON schema keeps service-level callers from passing non-serializable values that HTTP clients could never send.

Suggested change
id: SessionID,
const Metadata = Schema.Record(Schema.String, Schema.Json)

export type SessionUpdateData = {
body?: {
title?: string
metadata?: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion for the human to consider: the server schema and new route test both allow PATCH /session/:id with metadata: null to clear metadata, but the generated SDK update payload does not include null. If clearing with null is intended to be public SDK behavior, this generated type should include | null after the source/schema change and SDK regeneration.

summary_deletions: integer(),
summary_files: integer(),
summary_diffs: text({ mode: "json" }).$type<Snapshot.FileDiff[]>(),
metadata: text({ mode: "json" }).$type<Record<string, any>>(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion for the human to consider: this new DB type introduces any, which the style guide asks us to avoid. If the runtime schema is narrowed to JSON, this can also avoid widening the persisted shape to any here.

Suggested change
metadata: text({ mode: "json" }).$type<Record<string, any>>(),
metadata: text({ mode: "json" }).$type<Record<string, unknown>>(),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants