mirror of
https://github.com/sortedcord/omnia.git
synced 2026-07-22 12:02:49 +05:30
feat: Implemented Delta generator for time advancement
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
import { WorldState } from "@omnia/core";
|
||||
import { WorldState, SQLiteRepository } from "@omnia/core";
|
||||
import { LLMValidator, ValidationResult } from "./llm-validator.js";
|
||||
import { TimeDeltaGenerator, TimeDelta } from "./delta.js";
|
||||
import { ILLMProvider } from "@omnia/llm";
|
||||
|
||||
export interface ProcessResult extends ValidationResult {
|
||||
timeDelta?: TimeDelta;
|
||||
}
|
||||
|
||||
export class Architect {
|
||||
private validator: LLMValidator;
|
||||
private timeDeltaGenerator: TimeDeltaGenerator;
|
||||
|
||||
constructor(llmProvider: ILLMProvider) {
|
||||
constructor(llmProvider: ILLMProvider, private repo?: SQLiteRepository) {
|
||||
this.validator = new LLMValidator(llmProvider);
|
||||
this.timeDeltaGenerator = new TimeDeltaGenerator(llmProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,4 +27,41 @@ export class Architect {
|
||||
): Promise<ValidationResult> {
|
||||
return this.validator.validate(worldState, actorId, actionIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes, validates, generates deltas, applies them to the world state,
|
||||
* and persists the changes to the database.
|
||||
*/
|
||||
async processIntent(
|
||||
worldState: WorldState,
|
||||
actorId: string,
|
||||
actionIntent: string,
|
||||
): Promise<ProcessResult> {
|
||||
// 1. Validate the intent action
|
||||
const validation = await this.validateIntent(worldState, actorId, actionIntent);
|
||||
if (!validation.isValid) {
|
||||
return validation;
|
||||
}
|
||||
|
||||
// 2. Generate time delta for the valid action
|
||||
const timeDelta = await this.timeDeltaGenerator.generate(
|
||||
worldState,
|
||||
actorId,
|
||||
actionIntent,
|
||||
);
|
||||
|
||||
// 3. Apply the time delta to the world state clock
|
||||
worldState.clock.advance(timeDelta.minutesToAdvance);
|
||||
|
||||
// 4. Save and persist the updated world state
|
||||
if (this.repo) {
|
||||
this.repo.saveWorldState(worldState);
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
reason: validation.reason,
|
||||
timeDelta,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { z } from "zod";
|
||||
import { WorldState } from "@omnia/core";
|
||||
import { ILLMProvider } from "@omnia/llm";
|
||||
|
||||
export const TimeDeltaSchema = z.object({
|
||||
minutesToAdvance: z.number().int().nonnegative(),
|
||||
explanation: z.string(),
|
||||
});
|
||||
|
||||
export type TimeDelta = z.infer<typeof TimeDeltaSchema>;
|
||||
|
||||
export interface IDeltaGenerator<T> {
|
||||
generate(
|
||||
worldState: WorldState,
|
||||
actorId: string,
|
||||
actionIntent: string,
|
||||
): Promise<T>;
|
||||
}
|
||||
|
||||
export class TimeDeltaGenerator implements IDeltaGenerator<TimeDelta> {
|
||||
constructor(private llmProvider: ILLMProvider) {}
|
||||
|
||||
async generate(
|
||||
worldState: WorldState,
|
||||
actorId: string,
|
||||
actionIntent: string,
|
||||
): Promise<TimeDelta> {
|
||||
const systemPrompt = `
|
||||
You are the Time Delta Generator for the World Architect.
|
||||
Your task is to judge how much time (in minutes) a proposed action would logically take to execute in the physical world.
|
||||
Enforce realistic physical constraints:
|
||||
- Simple actions (e.g. picking up an unlocked key, looking around) take 1-2 minutes.
|
||||
- Walking between rooms takes 2-5 minutes.
|
||||
- Complex tasks (e.g. searching a room thoroughly, reading a book chapter, picking a lock) take 15-60 minutes.
|
||||
Return a structured JSON object containing:
|
||||
- "minutesToAdvance": integer (0 or more) representing the time elapsed.
|
||||
- "explanation": a brief explanation of why this amount of time is appropriate.
|
||||
`.trim();
|
||||
|
||||
const userContext = `
|
||||
=== CURRENT WORLD STATE ===
|
||||
Current Time: ${worldState.clock.get().toISOString()}
|
||||
World Details:
|
||||
${worldState.serialize()}
|
||||
|
||||
=== ACTION ===
|
||||
Actor ID: ${actorId}
|
||||
Action: "${actionIntent}"
|
||||
`.trim();
|
||||
|
||||
const response = await this.llmProvider.generateStructuredResponse({
|
||||
systemPrompt,
|
||||
userContext,
|
||||
schema: TimeDeltaSchema,
|
||||
});
|
||||
|
||||
if (!response.success || !response.data) {
|
||||
throw new Error(`Failed to generate time delta: ${response.error || "Unknown LLM error"}`);
|
||||
}
|
||||
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./llm-validator.js";
|
||||
export * from "./architect.js";
|
||||
export * from "./delta.js";
|
||||
|
||||
@@ -39,6 +39,7 @@ Exempt dialogue or speech actions from validation (consider them always valid).
|
||||
Enforce logical boundaries such as:
|
||||
- Spatial boundaries (an actor cannot grab an object in another location unless they are there).
|
||||
- Physical boundaries (an actor cannot open a locked drawer without a key or breaking it).
|
||||
- State Boundaries (an actor cannot perform a task if their state doesn't allow them to do so).
|
||||
- State/Attribute constraints.
|
||||
|
||||
You must respond with a JSON object containing:
|
||||
|
||||
Reference in New Issue
Block a user