Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
commit
03634b1ca3
11340 files changed
+3442369
No files matched your search
@@ -0,0 +1,281 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { createClientSessionState } from '@/lib/chat-runtime'
|
||||
import { $gatewayState } from '@/store/session'
|
||||
import { $sessionStates, dropSessionState, publishSessionState } from '@/store/session-states'
|
||||
|
||||
import { host } from './index'
|
||||
|
||||
// Plugins read app state exclusively through host.state — and before this
|
||||
// contract existed, only the PRIMARY workspace tab was reachable
|
||||
// ($activeSessionId). Clicking a tile never moved any plugin-visible atom,
|
||||
// and tile focus is pure renderer state that gateway RPC can never see, so
|
||||
// no plugin-side workaround was possible. These atoms are the plugin door to
|
||||
// the same focused-session signals the core statusbar reads
|
||||
// (use-statusbar-items.tsx).
|
||||
|
||||
describe('host.state focused-session atoms', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear()
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
async function setup() {
|
||||
const { host } = await import('@/sdk/index')
|
||||
const states = await import('@/store/session-states')
|
||||
const session = await import('@/store/session')
|
||||
|
||||
return { host, states, session }
|
||||
}
|
||||
|
||||
it('exposes readonly atoms for the focused session (runtime id, stored id, usage)', async () => {
|
||||
const { host } = await setup()
|
||||
|
||||
for (const key of ['focusedSessionId', 'focusedStoredSessionId', 'focusedUsage'] as const) {
|
||||
const store = host.state[key]
|
||||
expect(store, key).toBeDefined()
|
||||
expect(typeof store.get, key).toBe('function')
|
||||
expect(typeof store.listen, key).toBe('function')
|
||||
expect(typeof store.subscribe, key).toBe('function')
|
||||
}
|
||||
})
|
||||
|
||||
it('mirrors the primary session while no tile is focused', async () => {
|
||||
const { host, states } = await setup()
|
||||
|
||||
expect(host.state.focusedSessionId.get()).toBe(states.$focusedRuntimeId.get())
|
||||
expect(host.state.focusedStoredSessionId.get()).toBe(states.$focusedStoredSessionId.get())
|
||||
})
|
||||
|
||||
it('focusedUsage projects the focused session usage, null while unresolved', async () => {
|
||||
const { host, states } = await setup()
|
||||
|
||||
const focused = states.$focusedSessionState.get()
|
||||
expect(host.state.focusedUsage.get()).toBe(focused?.usage ?? null)
|
||||
})
|
||||
|
||||
it('exposes the registry source that owns the active gateway', async () => {
|
||||
const { host, session } = await setup()
|
||||
|
||||
session.setConnection({ connectionId: 'work', mode: 'remote' } as never)
|
||||
expect(host.state.connectionId.get()).toBe('work')
|
||||
|
||||
session.setConnection({ mode: 'local' } as never)
|
||||
expect(host.state.connectionId.get()).toBe('local')
|
||||
session.setConnection(null)
|
||||
})
|
||||
|
||||
it('follows the interacted tile while the primary-only atom stays put', async () => {
|
||||
const { host, session, states } = await setup()
|
||||
const tree = await import('@/components/pane-shell/tree/store')
|
||||
const model = await import('@/components/pane-shell/tree/model')
|
||||
const { registry } = await import('@/contrib/registry')
|
||||
|
||||
// A second chat zone holding a session tile, next to the main workspace.
|
||||
for (const id of ['workspace', 'session-tile:tile-a']) {
|
||||
registry.register({
|
||||
area: 'panes',
|
||||
data: id === 'workspace' ? { placement: 'main', uncloseable: true } : { placement: 'main' },
|
||||
id,
|
||||
render: () => null,
|
||||
title: id
|
||||
})
|
||||
}
|
||||
|
||||
tree.declareDefaultTree(
|
||||
model.split('row', [
|
||||
model.group(['workspace'], { active: 'workspace', id: 'grp-main' }),
|
||||
model.group(['session-tile:tile-a'], { active: 'session-tile:tile-a', id: 'grp-side' })
|
||||
])
|
||||
)
|
||||
|
||||
const primaryBefore = session.$activeSessionId.get()
|
||||
const primarySelection = session.$selectedStoredSessionId.get()
|
||||
|
||||
// Bind the tile to a live runtime with its own usage, so the readout
|
||||
// atoms (focusedSessionId / focusedUsage) — not just the navigation id —
|
||||
// are proven to follow the tile.
|
||||
const tileUsage = {
|
||||
calls: 3,
|
||||
input: 1200,
|
||||
output: 300,
|
||||
total: 1500,
|
||||
context_used: 42000,
|
||||
context_max: 200000,
|
||||
context_percent: 21,
|
||||
cost_usd: 0.0123
|
||||
}
|
||||
|
||||
states.$sessionTiles.set([{ storedSessionId: 'tile-a', runtimeId: 'runtime-tile-a' }])
|
||||
states.$sessionStates.set({
|
||||
'runtime-tile-a': { storedSessionId: 'tile-a', usage: tileUsage } as never
|
||||
})
|
||||
|
||||
// Focusing the tile zone moves the focused atoms onto the tile's session…
|
||||
tree.noteActiveTreeGroup('grp-side')
|
||||
expect(host.state.focusedStoredSessionId.get()).toBe('tile-a')
|
||||
expect(host.state.focusedSessionId.get()).toBe('runtime-tile-a')
|
||||
expect(host.state.focusedUsage.get()).toBe(tileUsage)
|
||||
// …while the primary-only atom a plugin used to rely on does not move.
|
||||
expect(host.state.activeSessionId.get()).toBe(primaryBefore)
|
||||
|
||||
// Focusing back homes to the primary's selection, whatever it is.
|
||||
tree.noteActiveTreeGroup('grp-main')
|
||||
expect(host.state.focusedStoredSessionId.get()).toBe(primarySelection)
|
||||
})
|
||||
})
|
||||
|
||||
describe('host.state.focusedSessionProfile', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear()
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
async function setup() {
|
||||
const { host } = await import('@/sdk/index')
|
||||
const profile = await import('@/store/profile')
|
||||
const session = await import('@/store/session')
|
||||
const states = await import('@/store/session-states')
|
||||
|
||||
return { host, profile, session, states }
|
||||
}
|
||||
|
||||
it('is a readonly atom that falls back to the gateway profile with no focused session', async () => {
|
||||
const { host, profile } = await setup()
|
||||
|
||||
expect(typeof host.state.focusedSessionProfile.get).toBe('function')
|
||||
expect(typeof host.state.focusedSessionProfile.listen).toBe('function')
|
||||
|
||||
profile.$activeGatewayProfile.set('newsanalyst')
|
||||
expect(host.state.focusedSessionProfile.get()).toBe('newsanalyst')
|
||||
profile.$activeGatewayProfile.set('default')
|
||||
})
|
||||
|
||||
it('resolves the focused session to the owner stamped on its session row, not the socket home', async () => {
|
||||
const { host, profile, session } = await setup()
|
||||
|
||||
// The gateway socket is homed on default (e.g. cold start), but the chat
|
||||
// on screen belongs to newsanalyst — the readout must say newsanalyst.
|
||||
profile.$activeGatewayProfile.set('default')
|
||||
session.$sessions.set([{ id: 'news-1', profile: 'newsanalyst' } as never])
|
||||
session.$selectedStoredSessionId.set('news-1')
|
||||
|
||||
expect(host.state.focusedSessionProfile.get()).toBe('newsanalyst')
|
||||
|
||||
// An uncached/unstamped id inherits the gateway profile (the old ladder).
|
||||
session.$selectedStoredSessionId.set('unknown-id')
|
||||
expect(host.state.focusedSessionProfile.get()).toBe('default')
|
||||
|
||||
session.$sessions.set([])
|
||||
session.$selectedStoredSessionId.set(null)
|
||||
})
|
||||
|
||||
it('fails closed when duplicate stored or lineage ids resolve to different connections', async () => {
|
||||
const { host, session } = await setup()
|
||||
|
||||
session.$sessions.set([
|
||||
{
|
||||
connection_id: 'source-a',
|
||||
id: 'shared-tip-a',
|
||||
_lineage_root_id: 'shared-root',
|
||||
profile: 'worker'
|
||||
} as never,
|
||||
{
|
||||
connection_id: 'source-b',
|
||||
id: 'shared-root',
|
||||
profile: 'worker'
|
||||
} as never
|
||||
])
|
||||
session.$selectedStoredSessionId.set('shared-root')
|
||||
|
||||
expect(host.state.focusedSessionOwner.get()).toBeNull()
|
||||
|
||||
session.$sessions.set([])
|
||||
session.$selectedStoredSessionId.set(null)
|
||||
})
|
||||
|
||||
it('fails closed when the same focused id has ambiguous owner hints', async () => {
|
||||
const { host, session } = await setup()
|
||||
|
||||
session.setSessionOwnerHint('ambiguous-hint', {
|
||||
connectionId: 'source-a',
|
||||
mode: 'remote',
|
||||
profile: 'worker',
|
||||
targetProfile: 'backend-worker-a'
|
||||
})
|
||||
session.setSessionOwnerHint('ambiguous-hint', {
|
||||
connectionId: 'source-b',
|
||||
mode: 'remote',
|
||||
profile: 'worker',
|
||||
targetProfile: 'backend-worker-b'
|
||||
})
|
||||
session.$sessions.set([
|
||||
{
|
||||
connection_id: 'source-a',
|
||||
id: 'ambiguous-hint',
|
||||
profile: 'worker'
|
||||
} as never
|
||||
])
|
||||
session.$selectedStoredSessionId.set('ambiguous-hint')
|
||||
|
||||
expect(host.state.focusedSessionOwner.get()).toBeNull()
|
||||
|
||||
session.$sessions.set([])
|
||||
session.$selectedStoredSessionId.set(null)
|
||||
})
|
||||
|
||||
it('keeps the focused session connection when same-named profiles share a handle', async () => {
|
||||
const { host, profile, session } = await setup()
|
||||
|
||||
profile.$activeGatewayProfile.set('default')
|
||||
session.setConnection({ connectionId: 'source-a', mode: 'remote' } as never)
|
||||
session.$sessions.set([
|
||||
{
|
||||
connection_id: 'source-b',
|
||||
id: 'shared-default',
|
||||
profile: 'default'
|
||||
} as never
|
||||
])
|
||||
session.$selectedStoredSessionId.set('shared-default')
|
||||
|
||||
expect(host.state.focusedSessionOwner.get()).toEqual({
|
||||
connectionId: 'source-b',
|
||||
profile: 'default'
|
||||
})
|
||||
|
||||
session.$sessions.set([])
|
||||
session.$selectedStoredSessionId.set(null)
|
||||
session.setConnection(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('host.state busy vs gateway', () => {
|
||||
afterEach(() => {
|
||||
$sessionStates.set({})
|
||||
$gatewayState.set('idle')
|
||||
})
|
||||
|
||||
it('exposes per-session turn-busy and does not treat gateway as busy', () => {
|
||||
const running = { ...createClientSessionState('stored-a'), busy: true }
|
||||
const idle = { ...createClientSessionState('stored-b'), busy: false }
|
||||
|
||||
publishSessionState('runtime-a', running)
|
||||
publishSessionState('runtime-b', idle)
|
||||
$gatewayState.set('open')
|
||||
|
||||
expect(host.state.busyBySession.get()).toEqual({ 'runtime-a': true, 'runtime-b': false })
|
||||
expect(host.state.gateway.get()).toBe('open')
|
||||
|
||||
dropSessionState('runtime-a')
|
||||
expect(host.state.busyBySession.get()['runtime-a']).toBeUndefined()
|
||||
expect(host.state.gateway.get()).toBe('open')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user