Download packages/agent-core-v2/test/session/sessionMetadata/sessionMetadata.test.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 22.4 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/agent-core-v2/test/session/sessionMetadata/sessionMetadata.test.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/packages/agent-core-v2/test/session/sessionMetadata/sessionMetadata.test.ts
-
curl -L -o sessionMetadata.test.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/agent-core-v2/test/session/sessionMetadata/sessionMetadata.test.ts
22.4 kB
| import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; | |
| import { SyncDescriptor } from '#/_base/di/descriptors'; | |
| import { DisposableStore } from '#/_base/di/lifecycle'; | |
| import { ServiceCollection } from '#/_base/di/serviceCollection'; | |
| import { TestInstantiationService } from '#/_base/di/test'; | |
| import { ILogService } from '#/_base/log/log'; | |
| import { ISessionIndexMirror } from '#/app/sessionIndex/sessionIndex'; | |
| import { ISessionContext, makeSessionContext } from '#/session/sessionContext/sessionContext'; | |
| import { ISessionMetadata } from '#/session/sessionMetadata/sessionMetadata'; | |
| import { SessionMetadata } from '#/session/sessionMetadata/sessionMetadataService'; | |
| import { ISessionStateService } from '#/session/state/sessionState'; | |
| import { SessionStateService } from '#/session/state/sessionStateService'; | |
| import { JsonAtomicDocumentStore } from '#/persistence/backends/node-fs/atomicDocumentStore'; | |
| import { IFileSystemStorageService } from '#/persistence/interface/storage'; | |
| import { IAtomicDocumentStore } from '#/persistence/interface/atomicDocumentStore'; | |
| import { InMemoryStorageService } from '#/persistence/backends/memory/inMemoryStorageService'; | |
| import { stubSessionIndexMirror } from '../../app/sessionIndex/stubs'; | |
| import { stubLog } from '../../_base/log/stubs'; | |
| const META_SCOPE = 'sessions/wd_test/s1/session-meta'; | |
| function createFreshMetadata(ix: TestInstantiationService): SessionMetadata { | |
| return ix | |
| .createChild(new ServiceCollection([ISessionStateService, new SessionStateService()])) | |
| .createInstance(SessionMetadata); | |
| } | |
| function makeContext(): ISessionContext { | |
| return makeSessionContext({ | |
| sessionId: 's1', | |
| workspaceId: 'wd_test', | |
| sessionDir: '/tmp/sessions/wd_test/s1', | |
| sessionScope: 'sessions/wd_test/s1', | |
| metaScope: META_SCOPE, | |
| cwd: '/tmp/sessions/wd_test/s1', | |
| }); | |
| } | |
| describe('SessionMetadata', () => { | |
| let disposables: DisposableStore; | |
| let ix: TestInstantiationService; | |
| let mirror: ReturnType<typeof stubSessionIndexMirror>; | |
| beforeEach(() => { | |
| disposables = new DisposableStore(); | |
| ix = disposables.add(new TestInstantiationService()); | |
| mirror = stubSessionIndexMirror(); | |
| ix.stub(ILogService, stubLog()); | |
| ix.stub(ISessionContext, makeContext()); | |
| ix.stub(ISessionIndexMirror, mirror); | |
| ix.set(ISessionStateService, new SyncDescriptor(SessionStateService)); | |
| ix.set(IFileSystemStorageService, new SyncDescriptor(InMemoryStorageService)); | |
| ix.set(IAtomicDocumentStore, new SyncDescriptor(JsonAtomicDocumentStore)); | |
| ix.set(ISessionMetadata, new SyncDescriptor(SessionMetadata)); | |
| }); | |
| afterEach(() => { | |
| disposables.dispose(); | |
| vi.restoreAllMocks(); | |
| }); | |
| it('creates an initial document on first read', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| expect(await meta.read()).toMatchObject({ | |
| id: 's1', | |
| archived: false, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| expect((await meta.read()).createdAt).toBeGreaterThan(0); | |
| }); | |
| it('update merges fields and bumps updatedAt', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| const before = (await meta.read()).updatedAt; | |
| await new Promise((r) => setTimeout(r, 2)); | |
| await meta.update({ title: 'hello' }); | |
| const next = await meta.read(); | |
| expect(next.title).toBe('hello'); | |
| expect(next.updatedAt).toBeGreaterThanOrEqual(before); | |
| }); | |
| it('update with touchUpdatedAt:false keeps the previous updatedAt', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| const before = (await meta.read()).updatedAt; | |
| await meta.update({ title: 'quiet' }, { touchUpdatedAt: false }); | |
| const next = await meta.read(); | |
| expect(next.title).toBe('quiet'); | |
| expect(next.updatedAt).toBe(before); | |
| }); | |
| it('setTitle / setArchived write through', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.setTitle('t'); | |
| await meta.setArchived(true); | |
| expect(await meta.read()).toMatchObject({ title: 't', titleKind: 'custom', archived: true }); | |
| }); | |
| it('sets a generated title while the metadata remains uncustomized', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await expect(meta.setGeneratedTitleIfUncustomized('generated title')).resolves.toBe(true); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: 'generated title', | |
| titleKind: 'generated', | |
| }); | |
| }); | |
| it('setTitle keeps updatedAt (rename must not reorder listings)', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| const before = (await meta.read()).updatedAt; | |
| await new Promise((r) => setTimeout(r, 2)); | |
| await meta.setTitle('renamed'); | |
| const next = await meta.read(); | |
| expect(next.title).toBe('renamed'); | |
| expect(next.updatedAt).toBe(before); | |
| }); | |
| it('setArchived records archivedAt without touching updatedAt; restore clears it', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| const before = (await meta.read()).updatedAt; | |
| await new Promise((r) => setTimeout(r, 2)); | |
| await meta.setArchived(true); | |
| const archived = await meta.read(); | |
| expect(archived.archived).toBe(true); | |
| expect(archived.archivedAt).toBeGreaterThan(before); | |
| expect(archived.updatedAt).toBe(before); | |
| await meta.setArchived(false); | |
| const restored = await meta.read(); | |
| expect(restored.archived).toBe(false); | |
| expect(restored.archivedAt).toBeUndefined(); | |
| expect(restored.updatedAt).toBe(before); | |
| }); | |
| it('registerAgent never bumps updatedAt — the agents map is structural', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| const before = (await meta.read()).updatedAt; | |
| await new Promise((r) => setTimeout(r, 2)); | |
| await meta.registerAgent('main', { homedir: '/tmp/h', type: 'main' }); | |
| const next = await meta.read(); | |
| expect(next.agents?.['main']?.homedir).toBe('/tmp/h'); | |
| expect(next.updatedAt).toBe(before); | |
| }); | |
| it('an explicit patch.updatedAt always wins (fork inherits the source recency)', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.update({ title: 'fork', updatedAt: 1234 }); | |
| const next = await meta.read(); | |
| expect(next.title).toBe('fork'); | |
| expect(next.updatedAt).toBe(1234); | |
| }); | |
| it('reads a loaded document without the archived field as not-archived', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| expect(await meta.read()).toMatchObject({ id: 's1', archived: false }); | |
| }); | |
| it('mirrors a boolean archived to the read model even when the loaded document lacks the field', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| expect(mirror.recorded).toEqual([]); | |
| await meta.update({ title: 'x' }); | |
| expect(mirror.recorded).toHaveLength(1); | |
| expect(mirror.recorded[0]).toMatchObject({ id: 's1', archived: false }); | |
| }); | |
| it('persists the authoritative document before recording to the mirror', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| const persistedAtRecord: Promise<Record<string, unknown> | undefined>[] = []; | |
| const baseRecord = mirror.record; | |
| mirror.record = (summary) => { | |
| persistedAtRecord.push(store.get<Record<string, unknown>>(META_SCOPE, 'state.json')); | |
| baseRecord(summary); | |
| }; | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| await meta.update({ title: 'durable-first' }); | |
| expect(persistedAtRecord).toHaveLength(2); | |
| const [atCreate, atUpdate] = await Promise.all(persistedAtRecord); | |
| expect(atCreate).toMatchObject({ id: 's1', archived: false }); | |
| expect(atUpdate).toMatchObject({ title: 'durable-first' }); | |
| }); | |
| it('a mirror failure degrades the read model but never fails the metadata mutation', async () => { | |
| mirror.record = () => { | |
| throw new Error('mirror down'); | |
| }; | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| await meta.update({ title: 'still fine' }); | |
| expect(await meta.read()).toMatchObject({ title: 'still fine' }); | |
| const fresh = createFreshMetadata(ix); | |
| expect(await fresh.read()).toMatchObject({ title: 'still fine' }); | |
| }); | |
| it('persists across instances', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.update({ title: 'persisted' }); | |
| const fresh = createFreshMetadata(ix); | |
| expect(await fresh.read()).toMatchObject({ id: 's1', title: 'persisted' }); | |
| }); | |
| it('backfills and persists missing agents/custom maps on a pre-fix document', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| expect(await meta.read()).toMatchObject({ agents: {}, custom: {} }); | |
| const fresh = createFreshMetadata(ix); | |
| const healed = await fresh.read(); | |
| expect(healed.agents).toEqual({}); | |
| expect(healed.custom).toEqual({}); | |
| expect(healed.updatedAt).toBe(1700000000000); | |
| }); | |
| it('normalizes the legacy customTitle field before callers read metadata', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| customTitle: 'legacy title', | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: 'legacy title', | |
| titleKind: 'custom', | |
| }); | |
| const fresh = createFreshMetadata(ix); | |
| await expect(fresh.read()).resolves.toMatchObject({ | |
| title: 'legacy title', | |
| titleKind: 'custom', | |
| }); | |
| }); | |
| it('trusts modern custom title state over a stale legacy customTitle', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| title: 'renamed title', | |
| isCustomTitle: true, | |
| customTitle: 'legacy custom title', | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: 'renamed title', | |
| titleKind: 'custom', | |
| }); | |
| await meta.update({ archived: true }); | |
| const fresh = createFreshMetadata(ix); | |
| await expect(fresh.read()).resolves.toMatchObject({ | |
| title: 'renamed title', | |
| titleKind: 'custom', | |
| archived: true, | |
| }); | |
| const persisted = await store.get<Record<string, unknown>>(META_SCOPE, 'state.json'); | |
| expect(persisted).toMatchObject({ isCustomTitle: true }); | |
| expect(persisted).not.toHaveProperty('customTitle'); | |
| }); | |
| it('migrates a legacy non-custom title to replaceable title state', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| title: 'prompt title', | |
| isCustomTitle: false, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: 'prompt title', | |
| titleKind: 'replaceable', | |
| }); | |
| const persisted = await store.get<Record<string, unknown>>(META_SCOPE, 'state.json'); | |
| expect(persisted).toMatchObject({ | |
| title: 'prompt title', | |
| titleKind: 'replaceable', | |
| isCustomTitle: false, | |
| }); | |
| }); | |
| it('honors a legacy writer custom marker over the stale titleKind it left behind', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| title: '用户手工标题', | |
| titleKind: 'replaceable', | |
| isCustomTitle: true, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: '用户手工标题', | |
| titleKind: 'custom', | |
| }); | |
| const persisted = await store.get<Record<string, unknown>>(META_SCOPE, 'state.json'); | |
| expect(persisted).toMatchObject({ titleKind: 'custom', isCustomTitle: true }); | |
| const fresh = createFreshMetadata(ix); | |
| await expect(fresh.read()).resolves.toMatchObject({ | |
| title: '用户手工标题', | |
| titleKind: 'custom', | |
| }); | |
| await expect(fresh.setGeneratedTitleIfUncustomized('generated title')).resolves.toBe(false); | |
| }); | |
| it('double-writes the derived isCustomTitle marker for v1 readers', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.setGeneratedTitleIfUncustomized('generated title'); | |
| await expect(store.get<Record<string, unknown>>(META_SCOPE, 'state.json')).resolves.toMatchObject( | |
| { titleKind: 'generated', isCustomTitle: false }, | |
| ); | |
| await meta.setTitle('user title'); | |
| await expect(store.get<Record<string, unknown>>(META_SCOPE, 'state.json')).resolves.toMatchObject( | |
| { titleKind: 'custom', isCustomTitle: true }, | |
| ); | |
| }); | |
| it('does not downgrade a modern titleKind on a legacy false marker', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| title: 'generated title', | |
| titleKind: 'generated', | |
| isCustomTitle: false, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: 'generated title', | |
| titleKind: 'generated', | |
| }); | |
| }); | |
| it.each([ | |
| [{ isCustomTitle: true, titleKind: 'generated' as const }, 'custom'], | |
| [{ isCustomTitle: true, titleKind: 'replaceable' as const }, 'custom'], | |
| [{ isCustomTitle: true }, 'custom'], | |
| [{ isCustomTitle: false, titleKind: 'custom' as const }, 'custom'], | |
| [{ isCustomTitle: false, titleKind: 'generated' as const }, 'generated'], | |
| [{ isCustomTitle: false }, 'replaceable'], | |
| [{ titleKind: 'generated' as const }, 'generated'], | |
| [{ customTitle: 'legacy title' }, 'custom'], | |
| [{}, 'replaceable'], | |
| ])('normalizes title state %j to titleKind %s', async (fields, expectedKind) => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| const title = 'customTitle' in fields ? undefined : 'some title'; | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| ...(title === undefined ? {} : { title }), | |
| ...fields, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| expect((await meta.read()).titleKind).toBe(expectedKind); | |
| }); | |
| it('migrates the title state once, not on every load', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| title: '用户手工标题', | |
| titleKind: 'replaceable', | |
| isCustomTitle: true, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const first = ix.get(ISessionMetadata); | |
| await first.ready; | |
| const setSpy = vi.spyOn(store, 'set'); | |
| const fresh = createFreshMetadata(ix); | |
| await fresh.ready; | |
| expect(setSpy).not.toHaveBeenCalled(); | |
| expect((await fresh.read()).titleKind).toBe('custom'); | |
| }); | |
| it('keeps a queued custom title when a generated title is enqueued afterward', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| const store = ix.get(IAtomicDocumentStore); | |
| const set = store.set.bind(store); | |
| let releaseWrite: (() => void) | undefined; | |
| let markWriteStarted: (() => void) | undefined; | |
| const writeStarted = new Promise<void>((resolve) => { | |
| markWriteStarted = resolve; | |
| }); | |
| const writeReleased = new Promise<void>((resolve) => { | |
| releaseWrite = resolve; | |
| }); | |
| let shouldBlock = true; | |
| vi.spyOn(store, 'set').mockImplementation(async (scope, key, value) => { | |
| if (shouldBlock) { | |
| shouldBlock = false; | |
| markWriteStarted?.(); | |
| await writeReleased; | |
| } | |
| await set(scope, key, value); | |
| }); | |
| const priorWrite = meta.update({ lastPrompt: 'hello' }); | |
| await writeStarted; | |
| const rename = meta.setTitle('user title'); | |
| const generated = meta.setGeneratedTitleIfUncustomized('generated title'); | |
| releaseWrite?.(); | |
| await priorWrite; | |
| await rename; | |
| await expect(generated).resolves.toBe(false); | |
| await expect(meta.read()).resolves.toMatchObject({ | |
| title: 'user title', | |
| titleKind: 'custom', | |
| }); | |
| }); | |
| it('leaves existing agents/custom maps untouched', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| agents: { main: { homedir: '/tmp/sessions/wd_test/s1/agents/main', type: 'main' } }, | |
| custom: { cwd: '/tmp/work' }, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| expect(await meta.read()).toMatchObject({ | |
| agents: { main: { homedir: '/tmp/sessions/wd_test/s1/agents/main', type: 'main' } }, | |
| custom: { cwd: '/tmp/work' }, | |
| }); | |
| }); | |
| it('fires onDidChangeMetadata with the changed keys after update', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| let fired = 0; | |
| let captured: { readonly changed: readonly string[] } | undefined; | |
| const sub = meta.onDidChangeMetadata((e) => { | |
| fired++; | |
| captured = e; | |
| }); | |
| await meta.update({ title: 'x' }); | |
| expect(fired).toBe(1); | |
| expect(captured).toEqual({ changed: ['title'] }); | |
| sub.dispose(); | |
| }); | |
| it('preserves every concurrently registered agent', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await Promise.all([ | |
| meta.registerAgent('agent-0', { | |
| labels: { swarmItem: 'src/a.ts' }, | |
| }), | |
| meta.registerAgent('agent-1', { | |
| labels: { swarmItem: 'src/b.ts' }, | |
| }), | |
| ]); | |
| expect(Object.keys((await meta.read()).agents ?? {}).sort()).toEqual([ | |
| 'agent-0', | |
| 'agent-1', | |
| ]); | |
| }); | |
| it('treats re-registering an unchanged agent as a no-op', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.registerAgent('main', { | |
| homedir: '/tmp/sessions/wd_test/s1/agents/main', | |
| type: 'main', | |
| parentAgentId: undefined, | |
| forkedFrom: undefined, | |
| labels: undefined, | |
| }); | |
| const before = (await meta.read()).updatedAt; | |
| await new Promise((r) => setTimeout(r, 2)); | |
| let fired = 0; | |
| const sub = meta.onDidChangeMetadata(() => { | |
| fired++; | |
| }); | |
| await meta.registerAgent('main', { | |
| homedir: '/tmp/sessions/wd_test/s1/agents/main', | |
| type: 'main', | |
| parentAgentId: undefined, | |
| forkedFrom: undefined, | |
| labels: undefined, | |
| }); | |
| expect(fired).toBe(0); | |
| expect((await meta.read()).updatedAt).toBe(before); | |
| sub.dispose(); | |
| }); | |
| it('stays a no-op when re-registering against a persisted document', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| agents: { | |
| main: { | |
| homedir: '/tmp/sessions/wd_test/s1/agents/main', | |
| type: 'main', | |
| parentAgentId: null, | |
| }, | |
| }, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.registerAgent('main', { | |
| homedir: '/tmp/sessions/wd_test/s1/agents/main', | |
| type: 'main', | |
| parentAgentId: undefined, | |
| forkedFrom: undefined, | |
| labels: undefined, | |
| }); | |
| expect((await meta.read()).updatedAt).toBe(1700000000000); | |
| }); | |
| it('updates changed fields on re-registration without bumping updatedAt', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.registerAgent('main', { | |
| homedir: '/tmp/sessions/wd_test/s1/agents/main', | |
| type: 'main', | |
| }); | |
| const before = (await meta.read()).updatedAt; | |
| await new Promise((r) => setTimeout(r, 2)); | |
| await meta.registerAgent('main', { | |
| homedir: '/tmp/sessions/wd_test/s1/agents/main', | |
| type: 'main', | |
| labels: { swarmItem: 'src/a.ts' }, | |
| }); | |
| const next = await meta.read(); | |
| expect(next.agents?.['main']?.labels).toEqual({ swarmItem: 'src/a.ts' }); | |
| expect(next.updatedAt).toBe(before); | |
| }); | |
| it('records the fresh summary into the session index mirror on update', async () => { | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| expect(mirror.recorded).toHaveLength(1); | |
| await meta.update({ title: 'mirrored' }); | |
| expect(mirror.recorded).toHaveLength(2); | |
| expect(mirror.recorded[1]).toMatchObject({ | |
| id: 's1', | |
| workspaceId: 'wd_test', | |
| title: 'mirrored', | |
| archived: false, | |
| }); | |
| expect(mirror.recorded[1]?.updatedAt).toBe((await meta.read()).updatedAt); | |
| }); | |
| it('does not re-record when loading an existing document', async () => { | |
| const store = ix.get(IAtomicDocumentStore); | |
| await store.set(META_SCOPE, 'state.json', { | |
| id: 's1', | |
| version: 2, | |
| createdAt: 1700000000000, | |
| updatedAt: 1700000000000, | |
| archived: false, | |
| agents: {}, | |
| custom: {}, | |
| }); | |
| const meta = ix.get(ISessionMetadata); | |
| await meta.ready; | |
| expect(mirror.recorded).toEqual([]); | |
| await meta.setArchived(true); | |
| expect(mirror.recorded).toHaveLength(1); | |
| expect(mirror.recorded[0]?.archived).toBe(true); | |
| }); | |
| }); | |