chore: user modifications
Some checks failed
Release Binaries / release (push) Has been cancelled

This commit is contained in:
Gemini AI
2025-12-28 01:03:54 +04:00
Unverified
parent 74001c7c3e
commit babce0e0a9
7 changed files with 157 additions and 17 deletions

View File

@@ -192,6 +192,16 @@ export interface InstanceData {
agentModelSelections: AgentModelSelection
sessionTasks?: SessionTasks // Multi-task chat support: tasks per session
sessionSkills?: Record<string, SkillSelection[]> // Selected skills per session
sessionMessages?: Record<
string,
Array<{
id: string
role: "user" | "assistant" | "system" | "tool"
content?: string
createdAt?: number
updatedAt?: number
}>
>
customAgents?: Array<{
name: string
description?: string

View File

@@ -26,6 +26,20 @@ const InstanceDataSchema = z.object({
messageHistory: z.array(z.string()).default([]),
agentModelSelections: z.record(z.string(), ModelPreferenceSchema).default({}),
sessionTasks: z.record(z.string(), z.array(TaskSchema)).optional(),
sessionMessages: z
.record(
z.string(),
z.array(
z.object({
id: z.string(),
role: z.enum(["user", "assistant", "system", "tool"]),
content: z.string().optional(),
createdAt: z.number().optional(),
updatedAt: z.number().optional(),
}),
),
)
.optional(),
sessionSkills: z
.record(
z.string(),
@@ -47,6 +61,7 @@ const EMPTY_INSTANCE_DATA: InstanceData = {
messageHistory: [],
agentModelSelections: {},
sessionTasks: {},
sessionMessages: {},
sessionSkills: {},
customAgents: [],
}

View File

@@ -8,6 +8,7 @@ const DEFAULT_INSTANCE_DATA: InstanceData = {
messageHistory: [],
agentModelSelections: {},
sessionTasks: {},
sessionMessages: {},
}
export class InstanceStore {

View File

@@ -11,6 +11,7 @@ const DEFAULT_INSTANCE_DATA: InstanceData = {
messageHistory: [],
agentModelSelections: {},
sessionTasks: {},
sessionMessages: {},
}
function isDeepEqual(a: unknown, b: unknown): boolean {
@@ -157,11 +158,13 @@ export class ServerStorage {
const messageHistory = Array.isArray(source.messageHistory) ? [...source.messageHistory] : []
const agentModelSelections = { ...(source.agentModelSelections ?? {}) }
const sessionTasks = { ...(source.sessionTasks ?? {}) }
const sessionMessages = { ...(source.sessionMessages ?? {}) }
return {
...source,
messageHistory,
agentModelSelections,
sessionTasks,
sessionMessages,
}
}

View File

@@ -10,6 +10,7 @@ const DEFAULT_INSTANCE_DATA: InstanceData = {
agentModelSelections: {},
sessionTasks: {},
sessionSkills: {},
sessionMessages: {},
customAgents: [],
}
@@ -25,6 +26,7 @@ function cloneInstanceData(data?: InstanceData | null): InstanceData {
agentModelSelections: { ...(source.agentModelSelections ?? {}) },
sessionTasks: { ...(source.sessionTasks ?? {}) },
sessionSkills: { ...(source.sessionSkills ?? {}) },
sessionMessages: { ...(source.sessionMessages ?? {}) },
customAgents: Array.isArray(source.customAgents) ? [...source.customAgents] : [],
}
}

View File

@@ -26,6 +26,7 @@ import { getUserScopedKey } from "../lib/user-storage"
import { loadSkillDetails } from "./skills"
import { serverApi } from "../lib/api-client"
import { nativeSessionApi } from "../lib/lite-mode"
import { ensureInstanceConfigLoaded, updateInstanceConfig, getInstanceConfig } from "./instance-config"
import type { Session } from "../types/session"
const log = getLogger("actions")
@@ -1284,6 +1285,37 @@ async function persistNativeMessages(
}
}
async function persistSdkMessages(
instanceId: string,
sessionId: string,
messages: Array<{
id: string
role: "user" | "assistant" | "system" | "tool"
content?: string
createdAt?: number
updatedAt?: number
}>,
): Promise<void> {
try {
await ensureInstanceConfigLoaded(instanceId)
const existing = getInstanceConfig(instanceId).sessionMessages ?? {}
const current = existing[sessionId] ?? []
const merged = [...current]
for (const message of messages) {
if (!merged.some((entry) => entry.id === message.id)) {
merged.push(message)
}
}
merged.sort((a, b) => (a.createdAt ?? 0) - (b.createdAt ?? 0))
const trimmed = merged.length > 200 ? merged.slice(-200) : merged
await updateInstanceConfig(instanceId, (draft) => {
draft.sessionMessages = { ...(draft.sessionMessages ?? {}), [sessionId]: trimmed }
})
} catch (error) {
log.warn("Failed to persist SDK messages", { instanceId, sessionId, error })
}
}
async function sendMessage(
instanceId: string,
sessionId: string,
@@ -1296,6 +1328,7 @@ async function sendMessage(
throw new Error("Instance not ready")
}
const isNative = instance.binaryPath === "__nomadarch_native__"
const isSdk = !isNative
const instanceSessions = sessions().get(instanceId)
const session = instanceSessions?.get(sessionId)
@@ -1587,6 +1620,24 @@ async function sendMessage(
updatedAt: completedAt,
},
])
} else if (isSdk) {
const completedAt = Date.now()
await persistSdkMessages(instanceId, sessionId, [
{
id: messageId,
role: "user",
content: resolvedPrompt,
createdAt: now,
updatedAt: now,
},
{
id: assistantMessageId,
role: "assistant",
content: assistantText,
createdAt: now,
updatedAt: completedAt,
},
])
}
return messageId
} catch (error: any) {

View File

@@ -486,26 +486,45 @@ async function fetchSessions(instanceId: string): Promise<void> {
})
}
if (isNative) {
const updates: Promise<unknown>[] = []
for (const [parentId, tasks] of Object.entries(sessionTasks)) {
if (!Array.isArray(tasks)) continue
for (const task of tasks as Array<{ taskSessionId?: string }>) {
const childId = task?.taskSessionId
if (!childId) continue
const childSession = sessionMap.get(childId)
if (!childSession) continue
if (childSession.parentId === parentId) continue
sessionMap.set(childId, {
...childSession,
parentId,
})
const updates: Promise<unknown>[] = []
for (const [parentId, tasks] of Object.entries(sessionTasks)) {
if (!Array.isArray(tasks)) continue
for (const task of tasks as Array<{ taskSessionId?: string }>) {
const childId = task?.taskSessionId
if (!childId) continue
const childSession = sessionMap.get(childId)
if (!childSession) continue
if (childSession.parentId === parentId) continue
sessionMap.set(childId, {
...childSession,
parentId,
})
if (isNative) {
updates.push(nativeSessionApi.updateSession(instanceId, childId, { parentId }).catch(() => undefined))
}
}
if (updates.length > 0) {
await Promise.allSettled(updates)
}
}
if (updates.length > 0) {
await Promise.allSettled(updates)
}
for (const [sessionId, tasks] of Object.entries(sessionTasks)) {
if (sessionMap.has(sessionId)) continue
if (!Array.isArray(tasks) || tasks.length === 0) continue
const existingSession = existingSessions?.get(sessionId)
sessionMap.set(sessionId, {
id: sessionId,
instanceId,
title: existingSession?.title ?? "Untitled",
parentId: existingSession?.parentId ?? null,
agent: existingSession?.agent ?? "",
model: existingSession?.model ?? { providerId: "", modelId: "" },
skills: existingSession?.skills ?? [],
version: existingSession?.version ?? "0",
time: existingSession?.time ?? { created: Date.now(), updated: Date.now() },
revert: existingSession?.revert,
tasks: tasks as any[],
})
}
const validSessionIds = new Set(sessionMap.keys())
@@ -1069,6 +1088,45 @@ async function loadMessages(instanceId: string, sessionId: string, force = false
apiMessagesInfo = (response as any).info || {} // Assuming 'info' might be on the response object itself for some cases
}
if (!isNative) {
await ensureInstanceConfigLoaded(instanceId)
const cachedMessages = getInstanceConfig(instanceId).sessionMessages?.[sessionId] ?? []
if (cachedMessages.length > 0) {
const existingIds = new Set<string>()
for (const apiMessage of apiMessages) {
const info = apiMessage.info || apiMessage
if (info?.id) {
existingIds.add(info.id)
}
}
for (const cached of cachedMessages) {
if (!cached?.id || existingIds.has(cached.id)) continue
apiMessages.push({
id: cached.id,
role: cached.role,
content: cached.content,
createdAt: cached.createdAt,
info: {
id: cached.id,
role: cached.role,
time: { created: cached.createdAt ?? Date.now() },
},
parts: cached.content
? [{ id: `part-${cached.id}`, type: "text", text: cached.content }]
: [],
})
existingIds.add(cached.id)
}
apiMessages.sort((a, b) => {
const aInfo = a.info || a
const bInfo = b.info || b
const aTime = aInfo.time?.created ?? aInfo.createdAt ?? 0
const bTime = bInfo.time?.created ?? bInfo.createdAt ?? 0
return aTime - bTime
})
}
}
const messagesInfo = new Map<string, any>()
const messages: Message[] = apiMessages.map((apiMessage: any) => {
const info = apiMessage.info || apiMessage