qlogicagent 2.7.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/agent.js +18 -18
  2. package/dist/cli.js +445 -433
  3. package/dist/index.js +444 -432
  4. package/dist/orchestration.js +6 -6
  5. package/dist/protocol.js +1 -1
  6. package/dist/types/agent/agent.d.ts +1 -1
  7. package/dist/types/agent/tool-loop.d.ts +1 -1
  8. package/dist/types/agent/tunable-defaults.d.ts +4 -0
  9. package/dist/types/agent/types.d.ts +7 -18
  10. package/dist/types/cli/handlers/agents-handler.d.ts +19 -0
  11. package/dist/types/cli/handlers/config-handler.d.ts +17 -0
  12. package/dist/types/cli/handlers/dream-handler.d.ts +5 -0
  13. package/dist/types/cli/handlers/files-handler.d.ts +15 -0
  14. package/dist/types/cli/handlers/media-handler.d.ts +13 -0
  15. package/dist/types/cli/handlers/memory-handler.d.ts +21 -0
  16. package/dist/types/cli/handlers/pet-handler.d.ts +28 -0
  17. package/dist/types/cli/handlers/product-handler.d.ts +32 -0
  18. package/dist/types/cli/handlers/project-handler.d.ts +19 -0
  19. package/dist/types/cli/handlers/session-handler.d.ts +38 -0
  20. package/dist/types/cli/handlers/settings-handler.d.ts +24 -0
  21. package/dist/types/cli/handlers/skills-handler.d.ts +20 -0
  22. package/dist/types/cli/handlers/solo-handler.d.ts +15 -0
  23. package/dist/types/cli/handlers/turn-handler.d.ts +17 -0
  24. package/dist/types/cli/main.d.ts +2 -2
  25. package/dist/types/cli/stdio-server.d.ts +90 -106
  26. package/dist/types/cli/tool-bootstrap.d.ts +4 -3
  27. package/dist/types/config/config.d.ts +1 -1
  28. package/dist/types/index.d.ts +2 -2
  29. package/dist/types/llm/index.d.ts +1 -31
  30. package/dist/types/orchestration/tool-cascade.d.ts +2 -2
  31. package/dist/types/protocol/methods.d.ts +153 -5
  32. package/dist/types/protocol/wire/agent-events.d.ts +2 -2
  33. package/dist/types/protocol/wire/agent-methods.d.ts +5 -3
  34. package/dist/types/protocol/wire/gateway-rpc.d.ts +125 -4
  35. package/dist/types/protocol/wire/index.d.ts +1 -1
  36. package/dist/types/protocol/wire/notification-payloads.d.ts +79 -1
  37. package/dist/types/runtime/execution/dream-agent.d.ts +1 -1
  38. package/dist/types/runtime/execution/forked-agent.d.ts +1 -1
  39. package/dist/types/runtime/hooks/context-compression.d.ts +1 -1
  40. package/dist/types/runtime/hooks/memory-hooks.d.ts +1 -1
  41. package/dist/types/runtime/infra/acp-types.d.ts +4 -0
  42. package/dist/types/runtime/infra/agent-paths.d.ts +22 -25
  43. package/dist/types/runtime/infra/agent-process.d.ts +1 -1
  44. package/dist/types/runtime/infra/builtin-providers.d.ts +36 -0
  45. package/dist/types/runtime/infra/checkpoint-backend.d.ts +1 -1
  46. package/dist/types/runtime/infra/index.d.ts +1 -2
  47. package/dist/types/runtime/infra/key-pool.d.ts +120 -0
  48. package/dist/types/runtime/infra/media-persistence.d.ts +26 -15
  49. package/dist/types/runtime/infra/model-registry.d.ts +187 -0
  50. package/dist/types/runtime/infra/project-instructions-store.d.ts +3 -3
  51. package/dist/types/runtime/infra/project-store.d.ts +3 -0
  52. package/dist/types/runtime/infra/token-budget.d.ts +2 -2
  53. package/dist/types/runtime/infra/worktree-backend.d.ts +1 -1
  54. package/dist/types/runtime/pet/index.d.ts +10 -0
  55. package/dist/types/runtime/pet/pet-consistency.d.ts +79 -0
  56. package/dist/types/runtime/pet/pet-context-injection.d.ts +8 -0
  57. package/dist/types/runtime/pet/pet-file-loader.d.ts +62 -0
  58. package/dist/types/runtime/pet/pet-growth-engine.d.ts +60 -0
  59. package/dist/types/runtime/pet/pet-reaction-service.d.ts +33 -0
  60. package/dist/types/runtime/pet/pet-skeleton.d.ts +70 -0
  61. package/dist/types/runtime/pet/pet-soul-service.d.ts +71 -0
  62. package/dist/types/runtime/session/group-session-split.d.ts +38 -0
  63. package/dist/types/runtime/session/index.d.ts +4 -2
  64. package/dist/types/runtime/session/session-locator.d.ts +24 -0
  65. package/dist/types/runtime/session/session-memory.d.ts +4 -4
  66. package/dist/types/runtime/session/session-persistence.d.ts +47 -46
  67. package/dist/types/runtime/session/session-state.d.ts +3 -5
  68. package/dist/types/skills/memory/local-memory-provider.d.ts +11 -1
  69. package/dist/types/skills/memory/local-store.d.ts +3 -2
  70. package/dist/types/skills/memory/memdir.d.ts +7 -4
  71. package/dist/types/skills/memory/memory-provider-factory.d.ts +2 -8
  72. package/dist/types/skills/permissions/denial-audit-log.d.ts +1 -1
  73. package/dist/types/skills/permissions/permission-classifier.d.ts +1 -1
  74. package/dist/types/skills/tools/search-tool.d.ts +1 -1
  75. package/dist/types/skills/tools.d.ts +3 -3
  76. package/dist/types/transport/acp-event-emitter.d.ts +1 -1
  77. package/dist/types/transport/acp-server.d.ts +2 -2
  78. package/package.json +2 -1
  79. package/dist/types/llm/adapters/aliyun-oss-file-upload-adapter.d.ts +0 -44
  80. package/dist/types/llm/adapters/gemini-file-upload-adapter.d.ts +0 -26
  81. package/dist/types/llm/adapters/hub-oss-file-upload-adapter.d.ts +0 -29
  82. package/dist/types/llm/adapters/index.d.ts +0 -10
  83. package/dist/types/llm/adapters/openai-file-upload-adapter.d.ts +0 -38
  84. package/dist/types/llm/adapters/volcengine-file-upload-adapter.d.ts +0 -24
  85. package/dist/types/llm/builtin-providers.d.ts +0 -10
  86. package/dist/types/llm/debug-transport.d.ts +0 -12
  87. package/dist/types/llm/file-upload-service.d.ts +0 -68
  88. package/dist/types/llm/gemini-schema-utils.d.ts +0 -17
  89. package/dist/types/llm/llm-client.d.ts +0 -43
  90. package/dist/types/llm/media-client.d.ts +0 -42
  91. package/dist/types/llm/media-transport.d.ts +0 -176
  92. package/dist/types/llm/model-catalog.d.ts +0 -82
  93. package/dist/types/llm/model-detection.d.ts +0 -22
  94. package/dist/types/llm/provider-def.d.ts +0 -203
  95. package/dist/types/llm/provider-registry.d.ts +0 -59
  96. package/dist/types/llm/provider-tool-api.d.ts +0 -44
  97. package/dist/types/llm/retry.d.ts +0 -37
  98. package/dist/types/llm/transport.d.ts +0 -281
  99. package/dist/types/llm/transports/anthropic-messages.d.ts +0 -65
  100. package/dist/types/llm/transports/gemini-cache-api.d.ts +0 -86
  101. package/dist/types/llm/transports/gemini-file-api.d.ts +0 -90
  102. package/dist/types/llm/transports/gemini-generatecontent.d.ts +0 -56
  103. package/dist/types/llm/transports/gemini-lyria-realtime.d.ts +0 -117
  104. package/dist/types/llm/transports/gemini-media.d.ts +0 -53
  105. package/dist/types/llm/transports/media-resolve.d.ts +0 -50
  106. package/dist/types/llm/transports/minimax-media.d.ts +0 -55
  107. package/dist/types/llm/transports/openai-chat.d.ts +0 -81
  108. package/dist/types/llm/transports/openai-media.d.ts +0 -24
  109. package/dist/types/llm/transports/openai-responses.d.ts +0 -63
  110. package/dist/types/llm/transports/qwen-media.d.ts +0 -50
  111. package/dist/types/llm/transports/realtime-transport.d.ts +0 -183
  112. package/dist/types/llm/transports/volcengine-grounding.d.ts +0 -58
  113. package/dist/types/llm/transports/volcengine-media.d.ts +0 -93
  114. package/dist/types/llm/transports/volcengine-responses.d.ts +0 -64
  115. package/dist/types/llm/transports/zhipu-media.d.ts +0 -82
  116. package/dist/types/llm/transports/zhipu-tool-api.d.ts +0 -35
  117. package/dist/types/runtime/infra/project-plan-store.d.ts +0 -27
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Pet Consistency Scorer — Vision model evaluation for character consistency (design §14.4).
3
+ *
4
+ * After generating SVGs (via skeleton or direct LLM), this module:
5
+ * 1. Renders each SVG state to compare against the reference/base
6
+ * 2. Uses Vision model to score visual consistency (0-10)
7
+ * 3. Retries generation if score < threshold
8
+ *
9
+ * Strategies used:
10
+ * - Structured Prompt: fixed character description + only vary action
11
+ * - Post-processing validation: Vision model scores after generation
12
+ * - Part presence check: verify required DOM structure exists
13
+ */
14
+ export interface ConsistencyResult {
15
+ state: string;
16
+ score: number;
17
+ passed: boolean;
18
+ feedback?: string;
19
+ }
20
+ export interface ConsistencyReport {
21
+ overallScore: number;
22
+ results: ConsistencyResult[];
23
+ passedAll: boolean;
24
+ retryStates: string[];
25
+ }
26
+ export interface ConsistencyOptions {
27
+ /** Minimum score to pass (0-10). Default: 6 */
28
+ threshold?: number;
29
+ /** Max retries per state. Default: 2 */
30
+ maxRetries?: number;
31
+ /** Reference SVG (base/idle state) to compare against */
32
+ referenceSvg: string;
33
+ /** Character description for context */
34
+ characterDesc: string;
35
+ }
36
+ declare const DEFAULT_THRESHOLD = 6;
37
+ declare const DEFAULT_MAX_RETRIES = 2;
38
+ /**
39
+ * Quick structural check: verify the SVG has consistent DOM structure.
40
+ * Returns a score 0-10 based on structural similarity to reference.
41
+ */
42
+ export declare function structuralConsistencyScore(referenceSvg: string, candidateSvg: string): number;
43
+ /**
44
+ * Build the Vision model prompt for consistency scoring.
45
+ */
46
+ export declare function buildConsistencyPrompt(characterDesc: string, stateName: string): string;
47
+ /**
48
+ * Parse Vision model response to extract score and feedback.
49
+ */
50
+ export declare function parseConsistencyResponse(response: string): {
51
+ score: number;
52
+ feedback: string;
53
+ };
54
+ /**
55
+ * Run the full consistency check pipeline.
56
+ * Takes generated SVGs, scores each against reference, returns report.
57
+ *
58
+ * The `visionScore` callback is optional — if not provided, only structural
59
+ * scoring is used (faster, no LLM cost, but less accurate).
60
+ */
61
+ export declare function evaluateConsistency(referenceSvg: string, stateSvgs: Record<string, string>, options?: {
62
+ threshold?: number;
63
+ }): ConsistencyReport;
64
+ /**
65
+ * Async consistency evaluation using Vision model for high-accuracy scoring.
66
+ * Falls back to structural scoring if Vision call fails.
67
+ */
68
+ export declare function evaluateConsistencyWithVision(referenceSvg: string, stateSvgs: Record<string, string>, visionScore: (referenceSvg: string, candidateSvg: string, state: string) => Promise<{
69
+ score: number;
70
+ feedback: string;
71
+ }>, options?: {
72
+ threshold?: number;
73
+ }): Promise<ConsistencyReport>;
74
+ /**
75
+ * Retry strategy: regenerate failed states with enhanced prompt.
76
+ * Returns a prompt modifier string that emphasizes consistency.
77
+ */
78
+ export declare function buildRetryPrompt(characterDesc: string, state: string, feedback: string, attempt: number): string;
79
+ export { DEFAULT_THRESHOLD, DEFAULT_MAX_RETRIES };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Pet Context Injection — injects pet soul into agent system prompt.
3
+ *
4
+ * When a pet is hatched, this adds a brief section to the system prompt
5
+ * so the LLM "knows" the pet exists and can occasionally respond in character.
6
+ */
7
+ import type { PetSoul } from "./pet-soul-service.js";
8
+ export declare function petContextInjection(soul: PetSoul | null): string;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Pet File Loader — loads, validates, and sanitizes .pet bundles.
3
+ *
4
+ * Design §14.2: .pet is a zip file containing manifest.json + SVG states + thumbnail.
5
+ * Design §16.2: Security — SVG sanitize (remove scripts, foreign objects, event handlers).
6
+ *
7
+ * This module handles:
8
+ * - Zip extraction
9
+ * - Manifest JSON Schema validation
10
+ * - SVG sanitization (whitelist-based)
11
+ * - File size enforcement
12
+ */
13
+ export interface PetManifest {
14
+ version: number;
15
+ name: string;
16
+ author: string;
17
+ created: string;
18
+ generator?: string;
19
+ source?: {
20
+ type: "image" | "text" | "dialogue";
21
+ prompt?: string;
22
+ };
23
+ dimensions: {
24
+ width: number;
25
+ height: number;
26
+ };
27
+ states: Record<string, {
28
+ file: string;
29
+ loop: boolean;
30
+ duration?: number;
31
+ }>;
32
+ eyeTracking?: {
33
+ enabled: boolean;
34
+ pupils: string[];
35
+ maxOffset: number;
36
+ };
37
+ colors?: {
38
+ primary: string;
39
+ secondary?: string;
40
+ accent?: string;
41
+ };
42
+ }
43
+ export interface PetFileBundle {
44
+ manifest: PetManifest;
45
+ svgs: Record<string, string>;
46
+ thumbnail?: string;
47
+ hash: string;
48
+ }
49
+ /**
50
+ * Load and validate a .pet file from disk.
51
+ * Returns a PetFileBundle with sanitized SVGs, or throws on validation failure.
52
+ */
53
+ export declare function loadPetFile(filePath: string): Promise<PetFileBundle>;
54
+ /**
55
+ * Validate manifest structure. Throws on invalid.
56
+ */
57
+ export declare function validatePetManifest(manifest: unknown): asserts manifest is PetManifest;
58
+ /**
59
+ * Sanitize SVG content — remove dangerous elements and attributes.
60
+ * Whitelist-based approach (design §16.2).
61
+ */
62
+ export declare function sanitizeSvg(svgContent: string): string;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * PetGrowthEngine — handles pet leveling, molting (脱壳升级), and ability unlocks.
3
+ *
4
+ * Design §13: Growth system
5
+ * - XP curve: level * 100 (linear P0, polynomial later)
6
+ * - Molting: every 5 levels triggers a "molt" event with visual upgrade
7
+ * - Abilities: unlocked at specific levels
8
+ * - Stats growth: each level-up slightly boosts one stat
9
+ */
10
+ import type { PetStats, PetSoul } from "./pet-soul-service.js";
11
+ export interface PetAbility {
12
+ id: string;
13
+ name: string;
14
+ description: string;
15
+ unlockedAtLevel: number;
16
+ }
17
+ export interface GrowthEvent {
18
+ type: "level_up" | "molt" | "ability_unlock";
19
+ level: number;
20
+ ability?: PetAbility;
21
+ moltStage?: number;
22
+ }
23
+ export interface MoltResult {
24
+ stage: number;
25
+ description: string;
26
+ statBoost: Partial<PetStats>;
27
+ }
28
+ export declare class PetGrowthEngine {
29
+ /**
30
+ * Calculate XP needed for next level.
31
+ * P0: linear 100*level
32
+ */
33
+ static xpForLevel(level: number): number;
34
+ /**
35
+ * Process XP gain and return all triggered growth events.
36
+ * Does NOT mutate the soul — caller is responsible for persisting.
37
+ */
38
+ static processXpGain(soul: PetSoul, xpGain: number): {
39
+ newLevel: number;
40
+ newXp: number;
41
+ events: GrowthEvent[];
42
+ statBoosts: Partial<PetStats>;
43
+ };
44
+ /**
45
+ * Get molt result for a given stage.
46
+ */
47
+ static getMoltResult(stage: number, currentStats: PetStats): MoltResult;
48
+ /**
49
+ * Get all unlocked abilities for a given level.
50
+ */
51
+ static getUnlockedAbilities(level: number): PetAbility[];
52
+ /**
53
+ * Get next upcoming ability.
54
+ */
55
+ static getNextAbility(level: number): PetAbility | null;
56
+ /**
57
+ * XP gain rules for different events.
58
+ */
59
+ static xpForEvent(event: string): number;
60
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * PetReactionService — probabilistic reaction generation after turns.
3
+ *
4
+ * P0: Local template pools (no LLM).
5
+ * P1+: LLM-generated personalized reactions via small model.
6
+ */
7
+ import type { PetSoul } from "./pet-soul-service.js";
8
+ export type ReactionPool = "greeting" | "completion" | "error" | "curiosity" | "bored" | "memory" | "tool_success";
9
+ export type ReactionStyle = "normal" | "thinking" | "excited" | "sleepy";
10
+ /**
11
+ * Determine whether a reaction should fire, and if so, return it.
12
+ * P0: uses local template pools.
13
+ */
14
+ export declare function maybeGenerateReaction(eventMethod: string): {
15
+ text: string;
16
+ style: ReactionStyle;
17
+ } | null;
18
+ export interface LLMReactionContext {
19
+ turnSummary: string;
20
+ soul: PetSoul;
21
+ }
22
+ /**
23
+ * Generate a personalized reaction via small LLM call.
24
+ * Returns null on failure or timeout (graceful degradation to template pool).
25
+ * Max 50 tokens, under 2s.
26
+ *
27
+ * @param ctx Context for the reaction
28
+ * @param llmGenerate External function to call LLM (injected to avoid coupling)
29
+ */
30
+ export declare function generateLLMReaction(ctx: LLMReactionContext, llmGenerate: (prompt: string, maxTokens: number) => Promise<string | null>): Promise<{
31
+ text: string;
32
+ style: ReactionStyle;
33
+ } | null>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * PetSkeleton — SVG skeleton parameterization system (design §14.3 Plan A).
3
+ *
4
+ * Core idea: generate ONE base skeleton via LLM, then render each state by
5
+ * only varying animation parameters (pose, expression, effects).
6
+ * This ensures visual consistency across states without repeated LLM calls.
7
+ *
8
+ * Pipeline:
9
+ * 1. LLM generates a base SVG skeleton with labeled parts
10
+ * 2. We parse and decompose it into movable parts
11
+ * 3. Each state applies different CSS @keyframes to the same skeleton
12
+ */
13
+ export interface PetSkeleton {
14
+ /** Raw SVG of the base pose (idle-like neutral pose) */
15
+ baseSvg: string;
16
+ /** Extracted part IDs found in the SVG */
17
+ parts: SkeletonPart[];
18
+ /** Color palette extracted from the base SVG */
19
+ colors: {
20
+ primary: string;
21
+ secondary: string;
22
+ accent?: string;
23
+ };
24
+ /** Character description used to generate this skeleton */
25
+ characterDesc: string;
26
+ }
27
+ export interface SkeletonPart {
28
+ id: string;
29
+ type: "body" | "head" | "left-eye" | "right-eye" | "left-arm" | "right-arm" | "accessory" | "effect";
30
+ /** CSS selector for this part within the SVG */
31
+ selector: string;
32
+ }
33
+ export interface StateAnimationParams {
34
+ body: BodyAnimation;
35
+ eyes: EyeExpression;
36
+ arms: ArmPose;
37
+ effects?: EffectOverlay[];
38
+ }
39
+ export type BodyAnimation = "breathe" | "sway" | "lean" | "tilt" | "shrink" | "bounce" | "still" | "float";
40
+ export type EyeExpression = "blink" | "lookup" | "focus" | "closed" | "wide" | "sparkle" | "dizzy" | "sleepy";
41
+ export type ArmPose = "sway" | "still" | "hammer" | "wave" | "raised" | "covering" | "hold" | "eat";
42
+ export type EffectOverlay = "zzz" | "sparkle" | "sweat" | "question" | "ellipsis" | "heart" | "exclaim" | "music";
43
+ export declare const STATE_ANIMATION_MAP: Record<string, StateAnimationParams>;
44
+ /**
45
+ * Generate the base skeleton prompt for LLM.
46
+ * The LLM generates ONE SVG with labeled groups that we can animate differently per state.
47
+ */
48
+ export declare function buildSkeletonPrompt(characterDesc: string): string;
49
+ /**
50
+ * Parse a skeleton SVG and identify parts.
51
+ */
52
+ export declare function parseSkeleton(svgText: string): SkeletonPart[];
53
+ /**
54
+ * Render a specific state by injecting CSS animations into the skeleton SVG.
55
+ * The skeleton remains identical — only the <style> block changes.
56
+ */
57
+ export declare function renderState(skeleton: PetSkeleton, state: string): string;
58
+ /**
59
+ * Extract primary/secondary colors from an SVG string.
60
+ * Looks for fill/stop-color attributes and picks the two most frequent.
61
+ */
62
+ export declare function extractColors(svgText: string): {
63
+ primary: string;
64
+ secondary: string;
65
+ };
66
+ /**
67
+ * Validate that a skeleton SVG has the required part structure.
68
+ * Returns list of missing parts (empty = valid).
69
+ */
70
+ export declare function validateSkeleton(svgText: string): string[];
@@ -0,0 +1,71 @@
1
+ /**
2
+ * PetSoulService — manages pet identity (hatching, persistence, stats).
3
+ *
4
+ * Hatching: deterministic identity via hash(userId) + LLM-generated soul.
5
+ * Persistence: stored in project workspace under .qlogicagent/pet/soul.json
6
+ */
7
+ export interface PetStats {
8
+ grip: number;
9
+ patience: number;
10
+ curiosity: number;
11
+ appetite: number;
12
+ humor: number;
13
+ }
14
+ export interface PetSoul {
15
+ name: string;
16
+ species: string;
17
+ personality: string;
18
+ catchphrase: string;
19
+ stats: PetStats;
20
+ rarity: string;
21
+ breed?: string;
22
+ breedColors?: {
23
+ primary: string;
24
+ secondary: string;
25
+ };
26
+ level: number;
27
+ experience: number;
28
+ hatchedAt: string;
29
+ }
30
+ /** Breed system (design §6.2): 7 breeds with deterministic hash selection. */
31
+ export interface PetBreed {
32
+ name: string;
33
+ colors: {
34
+ primary: string;
35
+ secondary: string;
36
+ };
37
+ rarity: string;
38
+ }
39
+ export declare class PetSoulService {
40
+ private workspaceDir;
41
+ private soul;
42
+ private storagePath;
43
+ constructor(workspaceDir: string);
44
+ /**
45
+ * Load existing soul from disk. Returns null if not hatched.
46
+ */
47
+ load(): PetSoul | null;
48
+ /**
49
+ * Hatch a new pet soul. Uses LLM for name/personality/catchphrase.
50
+ * If generateSoul is provided, uses it; otherwise falls back to defaults.
51
+ */
52
+ hatch(userId: string, generateSoul?: (rarity: string, stats: PetStats) => Promise<{
53
+ name: string;
54
+ personality: string;
55
+ catchphrase: string;
56
+ }>): Promise<PetSoul>;
57
+ /**
58
+ * Add experience points. Returns true if leveled up.
59
+ */
60
+ addExperience(xp: number): {
61
+ leveledUp: boolean;
62
+ level: number;
63
+ experience: number;
64
+ };
65
+ getSoul(): PetSoul | null;
66
+ /**
67
+ * Update soul (e.g., after growth/stat changes) and persist.
68
+ */
69
+ updateSoul(soul: PetSoul): void;
70
+ private persist;
71
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Group Session Auto-Split — detects idle group sessions and creates successor sessions.
3
+ *
4
+ * When a group chat message arrives and the last session activity was > N hours ago,
5
+ * the old session is sealed and a new session is created with:
6
+ * - previousSessionId linking to the predecessor
7
+ * - carryoverSummary (from predecessor's taskSummary or last messages)
8
+ * - Same groupKey, groupName, groupPlatform, projectId
9
+ *
10
+ * This prevents unbounded context growth in long-lived group chats.
11
+ */
12
+ import { type SessionMetadata } from "./session-persistence.js";
13
+ export interface GroupSplitResult {
14
+ /** Whether a split occurred */
15
+ split: boolean;
16
+ /** The session ID to use for the current turn (new or existing) */
17
+ activeSessionId: string;
18
+ /** If split, the sealed predecessor session ID */
19
+ sealedSessionId?: string;
20
+ }
21
+ /**
22
+ * Check whether a group session should be auto-split due to idle timeout.
23
+ * If yes, seal the old session and create a new successor.
24
+ *
25
+ * @param currentSession - The existing group session metadata
26
+ * @param projectRoot - The project workspace directory
27
+ * @returns Split result with the session ID to use
28
+ */
29
+ export declare function maybeAutoSplitGroupSession(currentSession: SessionMetadata, projectRoot: string): Promise<GroupSplitResult>;
30
+ /**
31
+ * Check whether a group session has exceeded MAX_TURNS hard limit.
32
+ * Called AFTER turn.end — soft-splits without interrupting the current turn.
33
+ *
34
+ * @param currentSession - The session that just finished a turn
35
+ * @param projectRoot - The project workspace directory
36
+ * @returns Split result (new session ready for next message, or no-op)
37
+ */
38
+ export declare function maybeHardLimitSplit(currentSession: SessionMetadata, projectRoot: string): Promise<GroupSplitResult>;
@@ -1,2 +1,4 @@
1
- export { SessionState, type SessionUsageSnapshot, type SessionCostSnapshot } from "./session-state.js";
2
- export { appendMessage, saveSessionState, updateSessionMetadata, loadSessionForResume, listSessions, deleteSession, pruneOldSessions, shouldGenerateTaskSummary, maybeGenerateTaskSummary, type SessionMetadata, type PersistedSession, type SessionListEntry, type TaskSummaryDeps, } from "./session-persistence.js";
1
+ export { SessionState, type SessionUsageSnapshot } from "./session-state.js";
2
+ export { SessionLocator } from "./session-locator.js";
3
+ export { appendMessage, saveSessionState, updateSessionMetadata, getSessionMetadata, loadSessionForResume, listSessions, deleteSession, pruneOldSessions, shouldGenerateTaskSummary, maybeGenerateTaskSummary, type SessionMetadata, type PersistedSession, type SessionListEntry, type TaskSummaryDeps, } from "./session-persistence.js";
4
+ export { maybeAutoSplitGroupSession, type GroupSplitResult } from "./group-session-split.js";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * SessionLocator — resolves session storage paths from projectId.
3
+ *
4
+ * Every session operation uses this locator to determine the correct
5
+ * filesystem path based on the session's owning projectId.
6
+ * When projectId is missing, falls back to scanning all projects.
7
+ */
8
+ export declare class SessionLocator {
9
+ /** Get sessions root directory for a given projectId. */
10
+ getSessionsRoot(projectId: string): string;
11
+ /** Get the workspace dir for a project. */
12
+ getProjectWorkspaceDir(projectId: string): string;
13
+ /** Get the session directory path for a given projectId + sessionId. */
14
+ getSessionDir(projectId: string, sessionId: string): string;
15
+ /**
16
+ * Resolve the workspaceDir for a session given its projectId.
17
+ * If projectId is not provided, scans all projects for the session directory.
18
+ */
19
+ resolveWorkspaceDir(sessionId: string, projectId?: string): string;
20
+ /** Get the active project's workspace dir (for new session creation when no projectId specified). */
21
+ getActiveProjectWorkspaceDir(): string;
22
+ /** Get the active project's ID. */
23
+ getActiveProjectId(): string;
24
+ }
@@ -1,9 +1,9 @@
1
1
  /**
2
- * SessionMemory 鈥?In-memory session message store with JSONL persistence.
2
+ * SessionMemoryIn-memory session message store with JSONL persistence.
3
3
  *
4
4
  * CC alignment: messages live in memory during the session lifetime.
5
5
  * JSONL is the sole persistent source of truth (for crash recovery).
6
- * Gateway never owns message data 鈥?Agent is the single authority.
6
+ * Gateway never owns message dataAgent is the single authority.
7
7
  *
8
8
  * Design:
9
9
  * - Map<sessionId, ChatMessage[]> holds active session messages
@@ -15,7 +15,7 @@ import type { ChatMessage } from "../../protocol/wire/index.js";
15
15
  export declare class SessionMemory {
16
16
  private sessions;
17
17
  private projectRoot;
18
- constructor(projectRoot?: string);
18
+ constructor(projectRoot: string);
19
19
  setProjectRoot(projectRoot: string): void;
20
20
  /**
21
21
  * Get messages for a session. Lazy-loads from JSONL on first access.
@@ -35,7 +35,7 @@ export declare class SessionMemory {
35
35
  initSession(sessionId: string): void;
36
36
  /**
37
37
  * Drop a session from memory (e.g., on session.ended).
38
- * Does NOT delete JSONL 鈥?data persists for future resume.
38
+ * Does NOT delete JSONLdata persists for future resume.
39
39
  */
40
40
  evictSession(sessionId: string): void;
41
41
  /**
@@ -1,113 +1,113 @@
1
1
  /**
2
- * Session Persistence 鈥?CC sessionRestore.ts + conversationRecovery.ts parity.
2
+ * Session Persistence CC sessionRestore.ts + conversationRecovery.ts parity.
3
3
  *
4
4
  * Enables conversation resume by persisting:
5
5
  * 1. Message transcript (JSONL-based, append-only)
6
- * 2. Cost snapshot (atomic JSON)
7
- * 3. Session metadata (model, cwd, agent mode)
6
+ * 2. Session metadata (flat JSON, atomic write)
8
7
  *
9
- * Storage layout:
10
- * <project>/.qlogicagent/sessions/<session-id>/ (when projectRoot provided)
11
- * ~/.qlogicagent/sessions/<session-id>/ (fallback)
12
- * transcript.jsonl 鈥?append-only message log
13
- * state.json 鈥?cost snapshot + metadata
8
+ * Storage layout (ALL data lives under project workspace, NEVER global):
9
+ * <project>/.qlogicagent/sessions/<session-id>/
10
+ * transcript.jsonl — append-only message log
11
+ * metadata.json — flat session metadata + usage stats
14
12
  *
15
13
  * Resume flow (CC processResumedConversation parity):
16
- * 1. loadSessionForResume(sessionId) 鈫?messages + cost
17
- * 2. Restore cost state into SessionState
14
+ * 1. loadSessionForResume(sessionId) messages + metadata
15
+ * 2. Restore usage state into SessionState
18
16
  * 3. Feed messages as initial context to agent
19
- *
20
- * Reference: claude-code src/utils/sessionRestore.ts
21
- * claude-code src/utils/conversationRecovery.ts
22
17
  */
23
18
  import type { ChatMessage } from "../../protocol/wire/index.js";
24
- import type { SessionCostSnapshot } from "./session-state.js";
19
+ import type { SessionUsageSnapshot } from "./session-state.js";
25
20
  export interface SessionMetadata {
26
21
  sessionId: string;
27
- createdAt: number;
28
- lastActiveAt: number;
22
+ projectId: string;
23
+ createdAt: string;
24
+ lastActiveAt: string;
29
25
  model?: string;
30
26
  cwd?: string;
31
27
  turnCount: number;
32
28
  messageCount: number;
33
- /** Title / description (auto-generated or user-set) */
34
29
  title?: string;
35
- /** Task summary generated by LLM (CC maybeGenerateTaskSummary parity) */
36
30
  taskSummary?: string;
37
- /** Timestamp of last task summary generation */
38
31
  taskSummaryGeneratedAt?: number;
39
- /** ISO timestamp 鈥?session pinned in UI */
40
32
  pinnedAt?: string;
41
- /** ISO timestamp 鈥?session archived (soft-deleted) */
42
33
  archivedAt?: string;
43
- /** Project ID this session belongs to */
44
- projectId?: string;
45
- /** Session type: personal or group */
34
+ sealedAt?: string;
35
+ previousSessionId?: string;
36
+ carryoverSummary?: string;
46
37
  type?: "personal" | "group";
47
- /** Owner user ID */
48
38
  ownerId?: string;
49
- /** Group key for group sessions */
50
39
  groupKey?: string;
51
- /** Group display name */
52
40
  groupName?: string;
53
- /** Group platform (wechat, dingtalk, etc.) */
54
41
  groupPlatform?: string;
42
+ totalInputTokens?: number;
43
+ totalOutputTokens?: number;
55
44
  }
56
45
  export interface PersistedSession {
57
46
  metadata: SessionMetadata;
58
47
  messages: ChatMessage[];
59
- costSnapshot?: SessionCostSnapshot;
60
48
  }
61
49
  export interface SessionListEntry {
62
50
  sessionId: string;
63
51
  title?: string;
64
- lastActiveAt: number;
52
+ lastActiveAt: string;
65
53
  messageCount: number;
66
54
  model?: string;
67
55
  pinnedAt?: string;
68
56
  archivedAt?: string;
69
- projectId?: string;
57
+ sealedAt?: string;
58
+ projectId: string;
70
59
  type?: "personal" | "group";
71
- createdAt?: number;
60
+ createdAt: string;
61
+ groupKey?: string;
62
+ previousSessionId?: string;
63
+ carryoverSummary?: string | null;
72
64
  }
65
+ /**
66
+ * Load session metadata only (lightweight — no transcript loading).
67
+ * Returns null if session doesn't exist or metadata is unreadable.
68
+ */
69
+ export declare function getSessionMetadata(sessionId: string, projectRoot: string): SessionMetadata | null;
73
70
  /**
74
71
  * Append a message to the session transcript.
75
72
  * Creates the session directory if it doesn't exist.
76
73
  * When turnId is provided, it acts as a per-turn boundary marker enabling
77
74
  * reconciliation with Gateway's token_usage records.
75
+ *
76
+ * Robustness: catches disk-full and I/O errors without crashing the agent.
77
+ * Returns false if the write fails.
78
78
  */
79
- export declare function appendMessage(sessionId: string, message: ChatMessage, projectRoot?: string, turnId?: string): Promise<void>;
79
+ export declare function appendMessage(sessionId: string, message: ChatMessage, projectRoot: string, turnId?: string): Promise<boolean>;
80
80
  /**
81
- * Save session state (cost + metadata) atomically.
81
+ * Save session metadata + usage stats atomically (flat structure).
82
82
  */
83
- export declare function saveSessionState(sessionId: string, costSnapshot: SessionCostSnapshot, metadata: Partial<SessionMetadata>, projectRoot?: string): Promise<void>;
83
+ export declare function saveSessionState(sessionId: string, usageSnapshot: SessionUsageSnapshot, metadata: Partial<SessionMetadata>, projectRoot: string): Promise<void>;
84
84
  /**
85
85
  * Update specific metadata fields of a session without touching cost data.
86
86
  * Used by session CRUD RPC (rename, pin, archive, move-to-project).
87
87
  */
88
- export declare function updateSessionMetadata(sessionId: string, patch: Partial<SessionMetadata>, projectRoot?: string): Promise<SessionMetadata | null>;
88
+ export declare function updateSessionMetadata(sessionId: string, patch: Partial<Record<keyof SessionMetadata, SessionMetadata[keyof SessionMetadata] | null>>, projectRoot: string): Promise<SessionMetadata | null>;
89
89
  /**
90
- * Load a persisted session for resume 鈥?CC loadConversationForResume parity.
90
+ * Load a persisted session for resume CC loadConversationForResume parity.
91
91
  *
92
92
  * Returns null if the session doesn't exist or is corrupted.
93
93
  */
94
- export declare function loadSessionForResume(sessionId: string, projectRoot?: string): Promise<PersistedSession | null>;
94
+ export declare function loadSessionForResume(sessionId: string, projectRoot: string): Promise<PersistedSession | null>;
95
95
  /**
96
- * List available sessions for resume 鈥?CC ResumeConversation picker.
96
+ * List available sessions for resume CC ResumeConversation picker.
97
97
  * Returns most-recent-first, up to `limit` entries.
98
98
  */
99
- export declare function listSessions(limit?: number, projectRoot?: string): Promise<SessionListEntry[]>;
99
+ export declare function listSessions(limit: number | undefined, projectRoot: string): Promise<SessionListEntry[]>;
100
100
  /**
101
101
  * Delete a session (cleanup).
102
102
  */
103
- export declare function deleteSession(sessionId: string, projectRoot?: string): Promise<void>;
103
+ export declare function deleteSession(sessionId: string, projectRoot: string): Promise<void>;
104
104
  /**
105
105
  * Prune old sessions beyond MAX_SESSIONS limit.
106
106
  * Deletes oldest sessions first.
107
107
  */
108
- export declare function pruneOldSessions(projectRoot?: string): Promise<number>;
108
+ export declare function pruneOldSessions(projectRoot: string): Promise<number>;
109
109
  export interface TaskSummaryDeps {
110
- transport: import("../../llm/transport.js").LLMTransport;
110
+ transport: import("@qlogic/provider-core").LLMTransport;
111
111
  apiKey: string;
112
112
  model: string;
113
113
  }
@@ -117,7 +117,8 @@ export interface TaskSummaryDeps {
117
117
  */
118
118
  export declare function shouldGenerateTaskSummary(metadata: SessionMetadata): boolean;
119
119
  /**
120
- * Generate and persist a task summary for a long session.
121
- * Fire-and-forget 鈥?errors are swallowed.
120
+ * Generate a concise session title from the user's first message.
121
+ * Lightweight LLM call — one-shot, no tool loop.
122
122
  */
123
- export declare function maybeGenerateTaskSummary(sessionId: string, metadata: SessionMetadata, recentMessages: ChatMessage[], deps: TaskSummaryDeps, projectRoot?: string): Promise<string | null>;
123
+ export declare function generateSessionTitle(userMessage: string, deps: TaskSummaryDeps): Promise<string | null>;
124
+ export declare function maybeGenerateTaskSummary(sessionId: string, metadata: SessionMetadata, recentMessages: ChatMessage[], deps: TaskSummaryDeps, projectRoot: string): Promise<string | null>;