/**
* Shared Context
*
* Task 5.3: Shared Context for Conversation Resources
* Constraint: Tool-owned state → Conversation-owned resources
*
* Witness Outcome: Tool-A creates "build-config" → Tool-B reads "build-config" without re-specification
*/
export interface Resource {
name: string;
data: any;
createdBy: string; // tool name
createdAt: number;
updatedAt: number;
}
/**
* Shared Context
*
* Stores resources that are accessible across all tools in a conversation.
* Resources persist in conversation state and survive server restarts.
*/
export class SharedContext {
private resources: Map<string, Resource> = new Map();
/**
* Create resource in shared context
*/
createResource(name: string, data: any, toolName: string): void {
const resource: Resource = {
name,
data,
createdBy: toolName,
createdAt: Date.now(),
updatedAt: Date.now(),
};
this.resources.set(name, resource);
console.error(`[SharedContext] Created resource: ${name} by ${toolName}`);
}
/**
* Get resource from shared context
*/
getResource(name: string): Resource | undefined {
return this.resources.get(name);
}
/**
* Update resource in shared context
*/
updateResource(name: string, data: any, toolName: string): boolean {
const resource = this.resources.get(name);
if (!resource) {
return false;
}
resource.data = data;
resource.updatedAt = Date.now();
this.resources.set(name, resource);
console.error(`[SharedContext] Updated resource: ${name} by ${toolName}`);
return true;
}
/**
* Delete resource from shared context
*/
deleteResource(name: string): boolean {
const deleted = this.resources.delete(name);
if (deleted) {
console.error(`[SharedContext] Deleted resource: ${name}`);
}
return deleted;
}
/**
* Check if resource exists
*/
hasResource(name: string): boolean {
return this.resources.has(name);
}
/**
* List all resources
*/
listResources(): Resource[] {
return Array.from(this.resources.values());
}
/**
* Get resource count
*/
getResourceCount(): number {
return this.resources.size;
}
/**
* Clear all resources
*/
clear(): void {
const count = this.resources.size;
this.resources.clear();
console.error(`[SharedContext] Cleared ${count} resources`);
}
/**
* Serialize for persistence
*
* Converts Map to array for JSON serialization
*/
serialize(): any {
return {
resources: Array.from(this.resources.entries()),
};
}
/**
* Deserialize from persistence
*
* Converts array back to Map after JSON deserialization
*/
static deserialize(data: any): SharedContext {
const context = new SharedContext();
if (data?.resources && Array.isArray(data.resources)) {
context.resources = new Map(data.resources);
}
return context;
}
/**
* Get state for debugging
*/
getState(): any {
return {
resourceCount: this.resources.size,
resources: Array.from(this.resources.values()).map(r => ({
name: r.name,
createdBy: r.createdBy,
createdAt: new Date(r.createdAt).toISOString(),
updatedAt: new Date(r.updatedAt).toISOString(),
})),
};
}
}