Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license

This commit is contained in:
yilsem committed 2026-09-05 13:26:46 +03:00
commit 03634b1ca3
11340 files changed
+3442369

No files matched your search

+281
View File
@@ -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')
})
})
+233
View File
@@ -0,0 +1,233 @@
import { afterEach, describe, expect, it } from 'vitest'
import { createClientSessionState } from '@/lib/chat-runtime'
import { host } from '@/sdk'
import { setActiveSessionId, setAwaitingResponse, setBusy } from '@/store/session'
import { clearAllSessionStates, publishSessionState } from '@/store/session-states'
describe('host.state turn flags', () => {
afterEach(() => {
setActiveSessionId(null)
setBusy(false)
setAwaitingResponse(false)
clearAllSessionStates()
})
it('uses the draft atoms when there is no runtime session', () => {
expect(host.state.busy.get()).toBe(false)
expect(host.state.awaitingResponse.get()).toBe(false)
setBusy(true)
setAwaitingResponse(true)
expect(host.state.busy.get()).toBe(true)
expect(host.state.awaitingResponse.get()).toBe(true)
})
it('reads the focused session slice once a runtime exists', () => {
setBusy(false)
setAwaitingResponse(false)
setActiveSessionId('rt-focus')
publishSessionState('rt-focus', {
...createClientSessionState('stored-focus'),
awaitingResponse: true,
busy: true
})
expect(host.state.busy.get()).toBe(true)
expect(host.state.awaitingResponse.get()).toBe(true)
publishSessionState('rt-focus', {
...createClientSessionState('stored-focus'),
awaitingResponse: false,
busy: true
})
expect(host.state.busy.get()).toBe(true)
expect(host.state.awaitingResponse.get()).toBe(false)
})
it('does not pick up a background session', () => {
setActiveSessionId('rt-focus')
publishSessionState('rt-focus', createClientSessionState('stored-focus'))
publishSessionState('rt-bg', {
...createClientSessionState('stored-bg'),
awaitingResponse: true,
busy: true
})
expect(host.state.busy.get()).toBe(false)
expect(host.state.awaitingResponse.get()).toBe(false)
})
it('follows a focused session tile, not the primary', async () => {
const tree = await import('@/components/pane-shell/tree/store')
const model = await import('@/components/pane-shell/tree/model')
const { registry } = await import('@/contrib/registry')
const { $sessionTiles } = await import('@/store/session-states')
// 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' })
])
)
// Primary chat is idle; the tile's session is mid-turn.
setActiveSessionId('rt-primary')
publishSessionState('rt-primary', createClientSessionState('stored-primary'))
$sessionTiles.set([{ runtimeId: 'rt-tile-a', storedSessionId: 'tile-a' }])
publishSessionState('rt-tile-a', {
...createClientSessionState('tile-a'),
awaitingResponse: true,
busy: true
})
// Focusing the tile zone moves the flags onto the tile's session…
tree.noteActiveTreeGroup('grp-side')
expect(host.state.busy.get()).toBe(true)
expect(host.state.awaitingResponse.get()).toBe(true)
// …and homing back to the workspace returns to the (idle) primary.
tree.noteActiveTreeGroup('grp-main')
expect(host.state.busy.get()).toBe(false)
expect(host.state.awaitingResponse.get()).toBe(false)
$sessionTiles.set([])
})
})
describe('host.connections', () => {
const desktopWindow = window as unknown as { hermesDesktop?: Window['hermesDesktop'] }
const originalDesktop = desktopWindow.hermesDesktop
const connection = (id: string, label: string) => ({
id,
kind: 'remote' as const,
label,
tokenPreview: null,
tokenSet: true,
url: `https://${id}.example`
})
const stubBridge = (list: () => Promise<unknown>) => {
desktopWindow.hermesDesktop = {
...originalDesktop,
connections: { list }
} as unknown as Window['hermesDesktop']
}
afterEach(() => {
desktopWindow.hermesDesktop = originalDesktop
})
it('returns the registry rows, not the envelope that carries them (#89823)', async () => {
stubBridge(async () => ({
connections: [connection('local', 'This Mac'), connection('homelab', 'Homelab')],
primary: 'local',
secureTokenStorage: true,
version: 2
}))
const connections = await host.connections()
expect(Array.isArray(connections)).toBe(true)
expect(connections.map(entry => entry.id)).toEqual(['local', 'homelab'])
expect(connections[1]).toMatchObject({ kind: 'remote', label: 'Homelab', url: 'https://homelab.example' })
})
it('folds the envelope-level primary id down onto the row that owns it', async () => {
stubBridge(async () => ({
connections: [connection('local', 'This Mac'), connection('homelab', 'Homelab')],
primary: 'homelab',
secureTokenStorage: true,
version: 2
}))
expect((await host.connections()).map(entry => [entry.id, entry.primary])).toEqual([
['local', false],
['homelab', true]
])
})
it('reads as a single-source desktop when the payload carries no rows', async () => {
stubBridge(async () => ({ primary: '', secureTokenStorage: true, version: 1 }))
await expect(host.connections()).resolves.toEqual([])
})
it('still rejects on a Desktop build without the connection registry', async () => {
desktopWindow.hermesDesktop = undefined
await expect(host.connections()).rejects.toThrow('This Desktop build has no connection registry')
})
})
describe('host workspace scope', () => {
afterEach(async () => {
host.setWorkspaceScope('sessions')
const tree = await import('@/components/pane-shell/tree/store')
tree.$newSessionTabAction.set(null)
tree.removeTreePane('plugin-workspace:scope-test')
})
it('registers plugin workspace chrome options', async () => {
const { registry } = await import('@/contrib/registry')
const close = host.openWorkspace('scope-test', {
dock: { pane: 'workspace', pos: 'right' },
headerVeto: true,
render: () => null,
title: 'Scoped',
uncloseable: true
})
expect(registry.getArea('panes').find(pane => pane.id === 'plugin-workspace:scope-test')).toMatchObject({
data: {
dock: { pane: 'workspace', pos: 'right' },
headerVeto: true,
uncloseable: true
}
})
close()
})
it('publishes the active workspace scope through one host seam', async () => {
const { $workspaceMode, $workspaceOwnerKey } = await import('@/components/pane-shell/workspace-scope')
expect(host.setWorkspaceScope('bots', 'connection-b::default')).toBe(true)
expect($workspaceMode.get()).toBe('bots')
expect($workspaceOwnerKey.get()).toBe('connection-b::default')
})
it('uses the shared tab action for an exact Bot owner without moving Sessions', async () => {
const tree = await import('@/components/pane-shell/tree/store')
const { $workspaceNewSessionTarget } = await import('@/components/pane-shell/workspace-scope')
const opened: string[] = []
const route = {
connectionId: 'connection-b',
mode: 'remote' as const,
profile: 'writer',
targetProfile: 'writer'
}
tree.$newSessionTabAction.set(() => opened.push('tab'))
host.newChat(route, { workspaceMode: 'bots', workspaceOwnerKey: 'bot:connection-b::writer' })
expect(opened).toEqual(['tab'])
expect($workspaceNewSessionTarget.get()).toEqual({ kind: 'route', route })
})
})
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,69 @@
import { describe, expect, it } from 'vitest'
import { planPluginOpenSession } from './plugin-open-session-plan'
describe('planPluginOpenSession', () => {
it('defaults to navigation: dial the worker, do not steal chrome', () => {
const plan = planPluginOpenSession({
activeProfile: 'default',
profile: 'worker'
})
expect(plan.switchWorkspace).toBeNull()
expect(plan.dialWithoutSwitching).toBe('worker')
expect(plan.showAllProfiles).toBe(true)
expect(plan.requireActiveProfileForHydration).toBe(false)
})
it('does not steal chrome even when keepAllProfilesScope is explicitly true', () => {
const plan = planPluginOpenSession({
activeProfile: 'default',
keepAllProfilesScope: true,
profile: 'worker'
})
expect(plan.switchWorkspace).toBeNull()
expect(plan.dialWithoutSwitching).toBe('worker')
expect(plan.showAllProfiles).toBe(true)
expect(plan.requireActiveProfileForHydration).toBe(false)
})
it('does not re-dial when chrome is already on that profile', () => {
const plan = planPluginOpenSession({
activeProfile: 'worker',
keepAllProfilesScope: true,
profile: 'worker'
})
expect(plan.switchWorkspace).toBeNull()
expect(plan.dialWithoutSwitching).toBeNull()
// Still restores the unified list: re-opening an already-live bot must not
// leave Sessions collapsed onto a profile whose forever-chat is hidden.
expect(plan.showAllProfiles).toBe(true)
})
it('treats keepAllProfilesScope:false as an explicit workspace switch', () => {
const plan = planPluginOpenSession({
activeProfile: 'default',
keepAllProfilesScope: false,
profile: 'worker'
})
expect(plan.switchWorkspace).toBe('worker')
expect(plan.dialWithoutSwitching).toBeNull()
expect(plan.showAllProfiles).toBe(false)
expect(plan.requireActiveProfileForHydration).toBe(true)
})
it('treats an empty profile as neither a dial nor a workspace switch', () => {
const plan = planPluginOpenSession({
activeProfile: 'default',
keepAllProfilesScope: true,
profile: ' '
})
expect(plan.switchWorkspace).toBeNull()
expect(plan.dialWithoutSwitching).toBeNull()
expect(plan.showAllProfiles).toBeNull()
})
})
@@ -0,0 +1,50 @@
/** How `host.openSession` should treat a named profile.
A plugin/Bot Mode open is navigation, not a workspace or chrome API-home
switch. `keepAllProfilesScope` defaults true (undefined counts as true).
Pass false for an explicit profile workspace switch. */
export interface PluginOpenSessionPlan {
/** Dial this profile's backend without making it chrome-home. */
dialWithoutSwitching: null | string
/** Hydration may wait until `$activeGatewayProfile` matches the target. */
requireActiveProfileForHydration: boolean
/** Unified Sessions list vs collapse onto the switched profile. Null = leave. */
showAllProfiles: boolean | null
/** Activate this profile as the workspace/API home. Null = do not steal chrome. */
switchWorkspace: null | string
}
export function planPluginOpenSession(input: {
activeProfile: string
keepAllProfilesScope?: boolean
profile: string
}): PluginOpenSessionPlan {
const profile = (input.profile ?? '').trim()
const activeProfile = (input.activeProfile ?? '').trim()
const keepWorkspace = input.keepAllProfilesScope !== false
if (!profile) {
return {
dialWithoutSwitching: null,
requireActiveProfileForHydration: false,
showAllProfiles: null,
switchWorkspace: null
}
}
if (keepWorkspace) {
return {
dialWithoutSwitching: profile !== activeProfile ? profile : null,
requireActiveProfileForHydration: false,
showAllProfiles: true,
switchWorkspace: null
}
}
return {
dialWithoutSwitching: null,
requireActiveProfileForHydration: true,
showAllProfiles: false,
switchWorkspace: profile
}
}
File diff suppressed because it is too large. Load diff
+54
View File
@@ -0,0 +1,54 @@
/**
* Runtime SDK injection — the other half of the vscode-module model. Bundled
* plugins resolve `@hermes/plugin-sdk` through the vite alias; RUNTIME-loaded
* plugins (disk / fetched) import the same specifier and get the same object:
* the loader rewrites bare specifiers to shim modules that re-export the
* live namespaces installed here. React ships as the app's singletons —
* a second React instance would break hooks.
*/
import * as React from 'react'
import * as jsxDevRuntime from 'react/jsx-dev-runtime'
import * as jsxRuntime from 'react/jsx-runtime'
import * as sdk from './index'
const GLOBALS = {
__HERMES_PLUGIN_SDK__: sdk,
__HERMES_REACT__: React,
__HERMES_REACT_JSX__: jsxRuntime,
__HERMES_REACT_JSX_DEV__: jsxDevRuntime
} as const
export function installPluginSdk(): void {
Object.assign(globalThis, GLOBALS)
}
/** Build a shim ESM blob that re-exports a global namespace's live members.
* Export names come from the namespace itself, so the list can't drift. */
function shimUrl(globalKey: keyof typeof GLOBALS): string {
const names = Object.keys(GLOBALS[globalKey]).filter(name => name !== 'default' && /^[A-Za-z_$][\w$]*$/.test(name))
const source =
`const m = globalThis.${globalKey};\n` +
`export default m.default ?? m;\n` +
// Guard the destructuring: `export const { } = m` is a syntax error, so
// only emit it when the namespace actually has named exports.
(names.length ? `export const { ${names.join(', ')} } = m;\n` : '')
return URL.createObjectURL(new Blob([source], { type: 'text/javascript' }))
}
let cached: Record<string, string> | null = null
/** Specifier -> shim URL map for the runtime loader (longest keys first). */
export function sdkImportMap(): Record<string, string> {
cached ??= {
'@hermes/plugin-sdk': shimUrl('__HERMES_PLUGIN_SDK__'),
'react/jsx-dev-runtime': shimUrl('__HERMES_REACT_JSX_DEV__'),
'react/jsx-runtime': shimUrl('__HERMES_REACT_JSX__'),
react: shimUrl('__HERMES_REACT__')
}
return cached
}