@loominal/shared
v0.2.0
Published
Shared types and utilities for Loominal multi-agent infrastructure
Downloads
17
Readme
@loominal/shared
Shared types and utilities for the Loominal multi-agent infrastructure.
Installation
npm install @loominal/shared
# or
pnpm add @loominal/sharedExports
The package provides three entry points:
// All exports (types + NATS utilities)
import { LoominalScope, NATSClient } from '@loominal/shared';
// Types only
import { LoominalScope, RegisteredAgent } from '@loominal/shared/types';
// NATS utilities only
import { NATSClient, createSubjectPatterns } from '@loominal/shared/nats';Unified Scope Model
Loominal uses a consistent 4-value scope model across all components (Pattern, Warp, Weft):
type LoominalScope = 'private' | 'personal' | 'team' | 'public';Scope Definitions
| Scope | Who Can Access | Where Stored | Use Case |
|-------|----------------|--------------|----------|
| private | Just this agent, this project | Project bucket, agent-keyed | Task-specific notes, session state |
| personal | Just this agent, everywhere | User bucket, agent-keyed | User preferences, schedules, personal profile |
| team | All agents in this project | Project bucket, shared | Project decisions, architecture, team learnings |
| public | All agents everywhere | Global bucket, shared | Public announcements, cross-project coordination |
Visual Model
┌─────────────────────────────────────────────┐
│ Global Bucket │
│ (loom-global-{feature}) │
│ │
│ public scope: all agents, all projects │
└─────────────────────────────────────────────┘
│
┌───────────────────────────────┼───────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ User Bucket A │ │ User Bucket B │ │ User Bucket C │
│ (loom-user-agent-a) │ │ (loom-user-agent-b) │ │ (loom-user-agent-c) │
│ │ │ │ │ │
│ personal scope: │ │ personal scope: │ │ personal scope: │
│ follows user across │ │ follows user across │ │ follows user across │
│ projects │ │ projects │ │ projects │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Project Bucket │
│ (loom-{feature}-{projectId}) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ team scope (shared.) │ │
│ │ │ │
│ │ Visible to all agents in this project │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ private scope │ │ private scope │ │ private scope │ │
│ │ (agent.A.) │ │ (agent.B.) │ │ (agent.C.) │ │
│ │ │ │ │ │ │ │
│ │ Only Agent A │ │ Only Agent B │ │ Only Agent C │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘Default Scopes by Operation
| Operation Type | Default Scope | Rationale |
|----------------|---------------|-----------|
| Agent registration | team | Agents are discoverable within their project |
| Work offers | team | Work is distributed within the project |
| Channel messages | team | Project communication |
| Task memories | private | Task-specific, session-bound |
| Core memories | personal | Identity follows the user across projects |
| Project decisions | team | Shared project knowledge |
Bucket Naming Helpers
import {
getUserBucket,
getProjectBucket,
getGlobalBucket,
selectBucket,
} from '@loominal/shared/types';
// User bucket for personal scope
getUserBucket('agent-123');
// → 'loom-user-agent-123'
// Project bucket for private/team scope
getProjectBucket('pattern', 'abc123');
// → 'loom-pattern-abc123'
// Global bucket for public scope
getGlobalBucket('pattern');
// → 'loom-global-pattern'
// Automatic bucket selection based on scope
selectBucket('personal', {
feature: 'pattern',
agentId: 'agent-123',
projectId: 'project-abc',
});
// → { bucket: 'loom-user-agent-123', keyPrefix: 'pattern.' }Migration from Legacy Values
If you're migrating from older versions of Loominal components:
import { migrateToUnifiedScope } from '@loominal/shared/types';
// Pattern legacy values
migrateToUnifiedScope('user'); // → 'personal'
migrateToUnifiedScope('project'); // → 'team'
migrateToUnifiedScope('shared'); // → 'team'
// Warp legacy visibility values
migrateToUnifiedScope('private'); // → 'private'
migrateToUnifiedScope('project-only'); // → 'team'
migrateToUnifiedScope('user-only'); // → 'personal'
migrateToUnifiedScope('public'); // → 'public'Migration mapping:
| Old Value (Pattern) | Old Value (Warp) | New Unified Value |
|---------------------|------------------|-------------------|
| scope: "private" + category: "core" | - | personal |
| scope: "private" + other categories | visibility: "private" | private |
| scope: "shared" | visibility: "project-only" | team |
| - | visibility: "user-only" | personal |
| - | visibility: "public" | public |
Type Reference
Scope Types
// The unified scope type
type LoominalScope = 'private' | 'personal' | 'team' | 'public';
// Context for bucket selection
interface BucketSelectionContext {
feature: string; // e.g., 'pattern', 'warp'
agentId: string; // Agent's unique identifier
projectId: string; // Project identifier
}
// Result of bucket selection
interface BucketSelection {
bucket: string; // The bucket name
keyPrefix?: string; // Optional key prefix within bucket
}Agent Types
type AgentStatus = 'online' | 'busy' | 'offline';
type AgentType = 'copilot-cli' | 'claude-code';
interface RegisteredAgent {
guid: string;
handle: string;
agentType: AgentType;
status: AgentStatus;
capabilities: string[];
boundaries: Boundary[];
hostname: string;
projectId: string;
visibility: AgentVisibility; // Legacy, prefer 'scope'
// ... other fields
}Work Item Types
type Boundary = 'corporate' | 'corporate-adjacent' | 'personal' | 'open-source';
type WorkItemStatus = 'pending' | 'assigned' | 'in-progress' | 'completed' | 'failed';
type Priority = 'low' | 'normal' | 'high' | 'critical';
interface BaseWorkItem {
id: string;
description: string;
boundary: Boundary;
priority: Priority;
requiredCapabilities: string[];
// ... other fields
}NATS Utilities
Subject Patterns
import { createSubjectPatterns } from '@loominal/shared/nats';
const subjects = createSubjectPatterns('my-project-id');
// Channel subjects
subjects.channels.publish('roadmap'); // → 'loom.my-project-id.channels.roadmap'
subjects.channels.subscribe('*'); // → 'loom.my-project-id.channels.*'
// Registry subjects
subjects.registry.put; // → 'loom.my-project-id.registry.put'
subjects.registry.get; // → 'loom.my-project-id.registry.get'
// Work subjects
subjects.work.offer('typescript'); // → 'loom.my-project-id.work.typescript'NATS Client
import { NATSClient } from '@loominal/shared/nats';
const client = new NATSClient({
url: 'nats://localhost:4222',
projectId: 'my-project',
});
await client.connect();
// Publish to channel
await client.publish(subjects.channels.publish('roadmap'), {
type: 'update',
content: 'Sprint planning complete',
});
// Subscribe to channel
const sub = await client.subscribe(subjects.channels.subscribe('*'));
for await (const msg of sub) {
console.log('Received:', msg.data);
}License
MIT