qlogicagent 2.6.1 → 2.9.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 (137) hide show
  1. package/dist/agent.js +19 -17
  2. package/dist/cli.js +634 -367
  3. package/dist/index.js +631 -364
  4. package/dist/orchestration.js +15 -15
  5. package/dist/protocol.js +1 -1
  6. package/dist/types/agent/agent.d.ts +4 -1
  7. package/dist/types/agent/tool-loop.d.ts +3 -1
  8. package/dist/types/agent/tunable-defaults.d.ts +22 -1
  9. package/dist/types/agent/types.d.ts +7 -9
  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 +11 -0
  16. package/dist/types/cli/handlers/pet-handler.d.ts +21 -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 +94 -100
  26. package/dist/types/cli/tool-bootstrap.d.ts +7 -8
  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/dag-scheduler.d.ts +46 -0
  31. package/dist/types/orchestration/index.d.ts +1 -1
  32. package/dist/types/orchestration/product-planner.d.ts +146 -0
  33. package/dist/types/orchestration/skill-improvement.d.ts +39 -0
  34. package/dist/types/orchestration/solo-evaluator.d.ts +26 -6
  35. package/dist/types/orchestration/solo-persistence.d.ts +5 -0
  36. package/dist/types/orchestration/tool-cascade.d.ts +2 -2
  37. package/dist/types/protocol/methods.d.ts +189 -6
  38. package/dist/types/protocol/notifications.d.ts +1 -1
  39. package/dist/types/protocol/wire/acp-protocol.d.ts +7 -0
  40. package/dist/types/protocol/wire/agent-events.d.ts +2 -2
  41. package/dist/types/protocol/wire/agent-methods.d.ts +6 -4
  42. package/dist/types/protocol/wire/gateway-rpc.d.ts +77 -4
  43. package/dist/types/protocol/wire/index.d.ts +1 -1
  44. package/dist/types/protocol/wire/memory-provider-lifecycle.d.ts +3 -1
  45. package/dist/types/protocol/wire/notification-payloads.d.ts +124 -4
  46. package/dist/types/runtime/execution/dream-agent.d.ts +33 -6
  47. package/dist/types/runtime/execution/forked-agent.d.ts +1 -1
  48. package/dist/types/runtime/execution/memory-decay.d.ts +17 -5
  49. package/dist/types/runtime/hooks/context-compression.d.ts +1 -1
  50. package/dist/types/runtime/hooks/memory-hooks.d.ts +10 -1
  51. package/dist/types/runtime/infra/acp-types.d.ts +92 -0
  52. package/dist/types/runtime/infra/agent-paths.d.ts +22 -25
  53. package/dist/types/runtime/infra/agent-process.d.ts +1 -1
  54. package/dist/types/runtime/infra/builtin-providers.d.ts +36 -0
  55. package/dist/types/runtime/infra/checkpoint-backend.d.ts +1 -1
  56. package/dist/types/runtime/infra/index.d.ts +1 -2
  57. package/dist/types/runtime/infra/key-pool.d.ts +120 -0
  58. package/dist/types/runtime/infra/media-persistence.d.ts +26 -15
  59. package/dist/types/runtime/infra/model-registry.d.ts +187 -0
  60. package/dist/types/runtime/infra/project-instructions-store.d.ts +3 -3
  61. package/dist/types/runtime/infra/project-store.d.ts +3 -0
  62. package/dist/types/runtime/infra/token-budget.d.ts +2 -2
  63. package/dist/types/runtime/infra/worktree-backend.d.ts +1 -1
  64. package/dist/types/runtime/pet/index.d.ts +8 -0
  65. package/dist/types/runtime/pet/pet-context-injection.d.ts +8 -0
  66. package/dist/types/runtime/pet/pet-file-loader.d.ts +62 -0
  67. package/dist/types/runtime/pet/pet-growth-engine.d.ts +60 -0
  68. package/dist/types/runtime/pet/pet-reaction-service.d.ts +33 -0
  69. package/dist/types/runtime/pet/pet-soul-service.d.ts +71 -0
  70. package/dist/types/runtime/prompt/environment-context.d.ts +10 -0
  71. package/dist/types/runtime/prompt/index.d.ts +1 -1
  72. package/dist/types/runtime/session/group-session-split.d.ts +38 -0
  73. package/dist/types/runtime/session/index.d.ts +4 -2
  74. package/dist/types/runtime/session/session-locator.d.ts +24 -0
  75. package/dist/types/runtime/session/session-memory.d.ts +4 -4
  76. package/dist/types/runtime/session/session-persistence.d.ts +47 -46
  77. package/dist/types/runtime/session/session-state.d.ts +3 -5
  78. package/dist/types/skills/index.d.ts +8 -2
  79. package/dist/types/skills/memory/implicit-extraction.d.ts +58 -0
  80. package/dist/types/skills/memory/local-embedding.d.ts +176 -0
  81. package/dist/types/skills/memory/local-memory-provider.d.ts +197 -0
  82. package/dist/types/skills/memory/local-store.d.ts +255 -0
  83. package/dist/types/skills/memory/memdir.d.ts +13 -5
  84. package/dist/types/skills/memory/memory-provider-factory.d.ts +48 -0
  85. package/dist/types/skills/memory/memory-tool.d.ts +30 -2
  86. package/dist/types/skills/permissions/denial-audit-log.d.ts +52 -0
  87. package/dist/types/skills/permissions/hook-runner.d.ts +14 -4
  88. package/dist/types/skills/permissions/permission-classifier.d.ts +1 -1
  89. package/dist/types/skills/skill-system/skill-lifecycle.d.ts +81 -0
  90. package/dist/types/skills/skill-system/skill-validation.d.ts +29 -0
  91. package/dist/types/skills/tools/exec-tool.d.ts +1 -1
  92. package/dist/types/skills/tools/search-tool.d.ts +1 -1
  93. package/dist/types/skills/tools.d.ts +3 -3
  94. package/dist/types/transport/acp-event-emitter.d.ts +1 -1
  95. package/dist/types/transport/acp-server.d.ts +7 -2
  96. package/package.json +19 -5
  97. package/dist/types/llm/adapters/aliyun-oss-file-upload-adapter.d.ts +0 -44
  98. package/dist/types/llm/adapters/gemini-file-upload-adapter.d.ts +0 -26
  99. package/dist/types/llm/adapters/hub-oss-file-upload-adapter.d.ts +0 -29
  100. package/dist/types/llm/adapters/index.d.ts +0 -10
  101. package/dist/types/llm/adapters/openai-file-upload-adapter.d.ts +0 -38
  102. package/dist/types/llm/adapters/volcengine-file-upload-adapter.d.ts +0 -24
  103. package/dist/types/llm/builtin-providers.d.ts +0 -10
  104. package/dist/types/llm/debug-transport.d.ts +0 -12
  105. package/dist/types/llm/file-upload-service.d.ts +0 -68
  106. package/dist/types/llm/gemini-schema-utils.d.ts +0 -17
  107. package/dist/types/llm/llm-client.d.ts +0 -43
  108. package/dist/types/llm/media-client.d.ts +0 -42
  109. package/dist/types/llm/media-transport.d.ts +0 -176
  110. package/dist/types/llm/model-catalog.d.ts +0 -53
  111. package/dist/types/llm/model-detection.d.ts +0 -22
  112. package/dist/types/llm/provider-def.d.ts +0 -203
  113. package/dist/types/llm/provider-registry.d.ts +0 -59
  114. package/dist/types/llm/provider-tool-api.d.ts +0 -44
  115. package/dist/types/llm/retry.d.ts +0 -37
  116. package/dist/types/llm/transport.d.ts +0 -281
  117. package/dist/types/llm/transports/anthropic-messages.d.ts +0 -65
  118. package/dist/types/llm/transports/gemini-cache-api.d.ts +0 -86
  119. package/dist/types/llm/transports/gemini-file-api.d.ts +0 -90
  120. package/dist/types/llm/transports/gemini-generatecontent.d.ts +0 -56
  121. package/dist/types/llm/transports/gemini-lyria-realtime.d.ts +0 -117
  122. package/dist/types/llm/transports/gemini-media.d.ts +0 -53
  123. package/dist/types/llm/transports/media-resolve.d.ts +0 -50
  124. package/dist/types/llm/transports/minimax-media.d.ts +0 -55
  125. package/dist/types/llm/transports/openai-chat.d.ts +0 -81
  126. package/dist/types/llm/transports/openai-media.d.ts +0 -24
  127. package/dist/types/llm/transports/openai-responses.d.ts +0 -63
  128. package/dist/types/llm/transports/qwen-media.d.ts +0 -50
  129. package/dist/types/llm/transports/realtime-transport.d.ts +0 -183
  130. package/dist/types/llm/transports/volcengine-grounding.d.ts +0 -58
  131. package/dist/types/llm/transports/volcengine-media.d.ts +0 -93
  132. package/dist/types/llm/transports/volcengine-responses.d.ts +0 -64
  133. package/dist/types/llm/transports/zhipu-media.d.ts +0 -82
  134. package/dist/types/llm/transports/zhipu-tool-api.d.ts +0 -35
  135. package/dist/types/runtime/infra/project-plan-store.d.ts +0 -27
  136. package/dist/types/skills/memory/qmemory-adapter.d.ts +0 -55
  137. package/dist/types/skills/memory/qmemory-http-client.d.ts +0 -16
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Key Pool — commercial-grade multi-key load balancing per provider.
3
+ *
4
+ * Supports: weighted-round-robin, least-busy, random strategies.
5
+ * Features: RPM/TPM sliding window, failure cooldown, health detection, auto-failover.
6
+ *
7
+ * Runtime state (inFlight, counters, health) is in-memory only — resets on restart.
8
+ * Persistent config (keys, weights, strategy) is managed by the caller (settings.json).
9
+ */
10
+ export type LoadBalanceStrategy = "weighted-round-robin" | "least-busy" | "random";
11
+ export type KeyHealthStatus = "healthy" | "degraded" | "cooldown" | "disabled";
12
+ /** Persistent key config (saved to settings.json). */
13
+ export interface KeyConfig {
14
+ id: string;
15
+ key: string;
16
+ label?: string;
17
+ weight: number;
18
+ enabled: boolean;
19
+ }
20
+ /** Persistent provider pool config (saved to settings.json). */
21
+ export interface ProviderPoolConfig {
22
+ providerId: string;
23
+ baseUrl?: string;
24
+ strategy: LoadBalanceStrategy;
25
+ keys: KeyConfig[];
26
+ rateLimit?: {
27
+ rpm?: number;
28
+ tpm?: number;
29
+ };
30
+ }
31
+ /** Acquired key handle — caller must call release() when done. */
32
+ export interface KeyHandle {
33
+ keyId: string;
34
+ apiKey: string;
35
+ providerId: string;
36
+ release: (result: KeyReleaseResult) => void;
37
+ }
38
+ export interface KeyReleaseResult {
39
+ success: boolean;
40
+ tokens?: number;
41
+ errorCode?: number;
42
+ retryAfter?: number;
43
+ }
44
+ /** Full status for a single key (config + runtime). */
45
+ export interface KeyStatus extends KeyConfig {
46
+ inFlight: number;
47
+ totalRequests: number;
48
+ totalTokens: number;
49
+ lastUsedAt: number;
50
+ lastErrorAt: number;
51
+ consecutiveErrors: number;
52
+ cooldownUntil: number;
53
+ healthStatus: KeyHealthStatus;
54
+ }
55
+ /** Full status for a provider pool. */
56
+ export interface PoolStatus {
57
+ providerId: string;
58
+ baseUrl?: string;
59
+ strategy: LoadBalanceStrategy;
60
+ rateLimit?: {
61
+ rpm?: number;
62
+ tpm?: number;
63
+ };
64
+ keys: KeyStatus[];
65
+ }
66
+ export declare class KeyPool {
67
+ private pools;
68
+ private runtimeStates;
69
+ constructor(configs?: ProviderPoolConfig[]);
70
+ /**
71
+ * Acquire the next available key for a provider.
72
+ * Returns a KeyHandle with release() that MUST be called when the request completes.
73
+ * Returns null if no healthy key is available.
74
+ */
75
+ acquireKey(providerId: string): KeyHandle | null;
76
+ /**
77
+ * Release a key after request completion. Updates health/stats.
78
+ */
79
+ private releaseKey;
80
+ addProvider(providerId: string, opts?: {
81
+ baseUrl?: string;
82
+ strategy?: LoadBalanceStrategy;
83
+ rateLimit?: {
84
+ rpm?: number;
85
+ tpm?: number;
86
+ };
87
+ }): void;
88
+ removeProvider(providerId: string): void;
89
+ addKey(providerId: string, key: string, opts?: {
90
+ id?: string;
91
+ label?: string;
92
+ weight?: number;
93
+ enabled?: boolean;
94
+ }): string;
95
+ removeKey(keyId: string): void;
96
+ updateKey(keyId: string, updates: Partial<Pick<KeyConfig, "label" | "weight" | "enabled">>): void;
97
+ /** Explicitly set a key's health status (e.g. after background validation). */
98
+ setKeyHealth(keyId: string, status: KeyHealthStatus): void;
99
+ setStrategy(providerId: string, strategy: LoadBalanceStrategy): void;
100
+ setRateLimit(providerId: string, rateLimit: {
101
+ rpm?: number;
102
+ tpm?: number;
103
+ }): void;
104
+ getPoolStatus(providerId: string): PoolStatus | null;
105
+ getAllStatus(): PoolStatus[];
106
+ getProviderIds(): string[];
107
+ hasProvider(providerId: string): boolean;
108
+ hasAvailableKey(providerId: string): boolean;
109
+ /** Export persistent config (for saving to settings.json). */
110
+ exportConfig(): ProviderPoolConfig[];
111
+ /** Reload from config (e.g., after settings.json changes on disk). */
112
+ reloadConfig(configs: ProviderPoolConfig[]): void;
113
+ private createInitialState;
114
+ private getHealthyCandidates;
115
+ private selectByStrategy;
116
+ private weightedRandom;
117
+ private leastBusy;
118
+ private pruneWindow;
119
+ private buildPoolStatus;
120
+ }
@@ -5,12 +5,13 @@
5
5
  * cloud URLs, this service downloads them to a persistent local directory
6
6
  * so the user can access them offline without manual intervention.
7
7
  *
8
- * Storage layout:
9
- * ~/.qlogicagent/media/
10
- * ├── <session-or-date>/
11
- * ├── image_20260520_143022_abc.png
12
- * │ ├── video_20260520_143055_def.mp4
13
- * │ └── audio_20260520_143100_ghi.mp3
8
+ * Storage layout (per persistence-storage-rules.md):
9
+ * <project>/.qlogicagent/sessions/<sessionId>/media/
10
+ * ├── image_20260520_143022_abc.png
11
+ * ├── video_20260520_143055_def.mp4
12
+ * └── audio_20260520_143100_ghi.mp3
13
+ *
14
+ * Media files belong to their session. No global media storage.
14
15
  *
15
16
  * Integration:
16
17
  * Called from the tool result pipeline in tool-loop.ts.
@@ -29,28 +30,36 @@ export interface MediaDownloadResult {
29
30
  }
30
31
  export interface MediaPersistenceConfig {
31
32
  /**
32
- * Project working directory. When set, media downloads to `{projectDir}/media/`.
33
- * Takes precedence over `mediaDir`. This is the preferred approach — generated
34
- * media files belong to the project, not the global user home.
33
+ * Project working directory. Media downloads to:
34
+ * `{projectDir}/.qlogicagent/sessions/{sessionId}/media/`
35
+ * This is the only correct location per persistence-storage-rules.
35
36
  */
36
37
  projectDir?: string;
37
- /** Base directory for media storage. Default: ~/.qlogicagent/media/ (fallback only). */
38
- mediaDir?: string;
39
38
  /** Maximum file size to download (bytes). Default: 500MB. */
40
39
  maxFileSize?: number;
41
40
  /** Download timeout per file (ms). Default: 300_000 (5 min). */
42
41
  timeoutMs?: number;
43
42
  }
44
43
  export declare class MediaPersistence {
45
- private mediaDir;
44
+ private projectDir;
46
45
  private readonly maxFileSize;
47
46
  private readonly timeoutMs;
48
47
  constructor(config?: MediaPersistenceConfig);
49
- /** Update media directory to use a specific project root. */
48
+ /** Update project root directory. */
50
49
  setProjectDir(projectDir: string): void;
50
+ /**
51
+ * Resolve the media directory for a given session.
52
+ * Path: <project>/.qlogicagent/sessions/<sessionId>/media/
53
+ */
54
+ private resolveMediaDir;
51
55
  /**
52
56
  * Download a remote URL to local storage.
53
57
  * Returns the local file path and metadata.
58
+ *
59
+ * Robustness:
60
+ * - Validates path length (Windows 260 char limit)
61
+ * - Cleans up partial files on download failure/timeout
62
+ * - Handles abort/network errors gracefully
54
63
  */
55
64
  download(remoteUrl: string, hint?: {
56
65
  type?: string;
@@ -66,6 +75,8 @@ export declare class MediaPersistence {
66
75
  }, log?: {
67
76
  warn: (msg: string) => void;
68
77
  }): Promise<MediaDownloadResult[]>;
69
- /** Get the base media directory path. */
70
- getMediaDir(): string;
78
+ /** Get the media directory path for a session. */
79
+ getMediaDir(sessionId?: string): string;
80
+ /** Get the project directory (for testing/inspection). */
81
+ getProjectDir(): string | null;
71
82
  }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Model Registry — centralized model pool + per-purpose binding.
3
+ *
4
+ * Architecture: User adds Provider keys → enables models → binds each purpose to a model.
5
+ * Any code needing a model calls `registry.getActiveModel(purpose)`.
6
+ * Turn handler, media handler, STT, TTS — all go through this single source of truth.
7
+ *
8
+ * Persistence: ~/.qlogicagent/settings.json
9
+ * Runtime state (key health, inFlight): in-memory via KeyPool
10
+ */
11
+ import { type ProviderPoolConfig, type KeyConfig, type LoadBalanceStrategy, type KeyHandle, type PoolStatus } from "./key-pool.js";
12
+ import { type ModelInfo, type ProviderDef } from "@qlogic/provider-core";
13
+ export type RegistryChangeCallback = () => void;
14
+ /** Purpose categories for model routing. */
15
+ export type ModelPurpose = "textGeneration" | "smallModel" | "stt" | "tts" | "imageGeneration" | "imageUnderstanding" | "videoGeneration" | "videoUnderstanding" | "threeDGeneration" | "embedding" | "voiceClone" | "musicGeneration" | "realtimeAudio" | "realtimeVideo";
16
+ /** A model entry in the available model pool. */
17
+ export interface ModelEntry {
18
+ id: string;
19
+ provider: string;
20
+ model: string;
21
+ displayName: string;
22
+ purposes: ModelPurpose[];
23
+ baseUrl?: string;
24
+ enabled: boolean;
25
+ }
26
+ /** Per-purpose binding: maps purpose → model ID. */
27
+ export type PurposeBindings = Partial<Record<ModelPurpose, string>>;
28
+ /** Persistent settings.json schema (new architecture). */
29
+ export interface ModelRegistryConfig {
30
+ providers: ProviderPoolConfig[];
31
+ models: ModelEntry[];
32
+ bindings: PurposeBindings;
33
+ tunables?: Record<string, unknown>;
34
+ }
35
+ /** Resolved model ready for API call. */
36
+ export interface ResolvedModel {
37
+ provider: string;
38
+ model: string;
39
+ apiKey: string;
40
+ baseUrl?: string;
41
+ keyHandle: KeyHandle;
42
+ }
43
+ export declare class ModelRegistry {
44
+ private keyPool;
45
+ private models;
46
+ private bindings;
47
+ private settingsPath;
48
+ private changeListeners;
49
+ constructor(config?: ModelRegistryConfig);
50
+ /**
51
+ * Get the currently bound model for a purpose, with a live API key from the pool.
52
+ * Returns null if purpose is not bound or no key is available.
53
+ *
54
+ * IMPORTANT: Caller MUST call result.keyHandle.release({ success, tokens? }) when done.
55
+ */
56
+ getActiveModel(purpose: ModelPurpose): ResolvedModel | null;
57
+ /**
58
+ * Peek at the bound model for a purpose WITHOUT acquiring a key.
59
+ * Useful for UI display, description generation, etc.
60
+ */
61
+ peekActiveModel(purpose: ModelPurpose): ModelEntry | null;
62
+ /**
63
+ * Check if a purpose has an available model + key (without acquiring).
64
+ */
65
+ isAvailable(purpose: ModelPurpose): boolean;
66
+ /**
67
+ * Resolve a model name for a purpose, falling back to textGeneration if not bound.
68
+ * Returns the raw model string (e.g. "deepseek-v4-flash") or null if nothing configured.
69
+ * Does NOT acquire a key — use for cases where the caller already has transport/key.
70
+ */
71
+ resolveModelForPurpose(purpose: ModelPurpose): string | null;
72
+ addProvider(providerId: string, opts?: {
73
+ baseUrl?: string;
74
+ strategy?: LoadBalanceStrategy;
75
+ rateLimit?: {
76
+ rpm?: number;
77
+ tpm?: number;
78
+ };
79
+ }): void;
80
+ removeProvider(providerId: string): void;
81
+ addKey(providerId: string, key: string, opts?: {
82
+ label?: string;
83
+ weight?: number;
84
+ }): string;
85
+ removeKey(keyId: string): void;
86
+ updateKey(keyId: string, updates: Partial<Pick<KeyConfig, "label" | "weight" | "enabled">>): void;
87
+ setKeyHealth(keyId: string, status: "healthy" | "degraded" | "cooldown" | "disabled"): void;
88
+ setStrategy(providerId: string, strategy: LoadBalanceStrategy): void;
89
+ addModel(entry: Omit<ModelEntry, "id"> & {
90
+ id?: string;
91
+ }): string;
92
+ removeModel(id: string): void;
93
+ enableModel(id: string): void;
94
+ disableModel(id: string): void;
95
+ listModels(filter?: {
96
+ purpose?: ModelPurpose;
97
+ provider?: string;
98
+ enabledOnly?: boolean;
99
+ }): ModelEntry[];
100
+ getModel(id: string): ModelEntry | null;
101
+ setBinding(purpose: ModelPurpose, modelId: string): void;
102
+ removeBinding(purpose: ModelPurpose): void;
103
+ getBinding(purpose: ModelPurpose): ModelEntry | null;
104
+ getAllBindings(): Record<string, ModelEntry | null>;
105
+ getProviderStatus(providerId: string): PoolStatus | null;
106
+ getAllProviderStatus(): PoolStatus[];
107
+ /** Save current config to settings.json. Preserves non-model fields (tunables, theme, etc.). */
108
+ save(): void;
109
+ /** Load config from settings.json. Returns false if file not found or parse error. */
110
+ load(): boolean;
111
+ /** Export full config (for serialization/transfer). */
112
+ exportConfig(): ModelRegistryConfig;
113
+ /**
114
+ * Read a tunable value from settings.json tunables section.
115
+ * Returns undefined if not set. Does NOT write — read-only accessor.
116
+ */
117
+ getTunable<T = unknown>(key: string): T | undefined;
118
+ private _providerRegistry;
119
+ private getProviderRegistry;
120
+ /**
121
+ * Get model metadata (streamRequired, contextWindow, etc.) from the merged
122
+ * provider-core registry. Replaces direct `this.registry.getModelInfo(...)`.
123
+ */
124
+ getModelInfo(providerId: string, modelId: string): ModelInfo | undefined;
125
+ /**
126
+ * Get the default model id for a provider (from builtin-providers).
127
+ * Replaces `this.registry.getProvider(provider)?.defaultModel`.
128
+ */
129
+ getProviderDefaultModel(providerId: string): string | undefined;
130
+ /**
131
+ * List all known provider definitions (builtin + catalog).
132
+ * Replaces `this.registry.listProviders()`.
133
+ */
134
+ listProviderDefs(): ProviderDef[];
135
+ /**
136
+ * Resolve an API key for a provider via env vars (fallback when KeyPool has no key).
137
+ * Replaces `this.registry.resolveApiKey(providerId)`.
138
+ */
139
+ resolveProviderApiKey(providerId: string): string | undefined;
140
+ /**
141
+ * Register a callback to be notified when registry state changes
142
+ * (binding change, model add/remove, key change, save/load).
143
+ * Returns an unsubscribe function.
144
+ */
145
+ onChange(callback: RegistryChangeCallback): () => void;
146
+ private emitChange;
147
+ /**
148
+ * Snapshot one available key for a provider WITHOUT holding it (for legacy flat-map consumers).
149
+ * Returns null if no healthy key exists.
150
+ */
151
+ getKeyForProvider(providerId: string): string | null;
152
+ /**
153
+ * Snapshot one key per provider (for media tools flat apiKeys map).
154
+ */
155
+ snapshotProviderKeys(): Record<string, string>;
156
+ private getProviderBaseUrl;
157
+ }
158
+ export declare const ALL_PURPOSES: ModelPurpose[];
159
+ /**
160
+ * Get the global ModelRegistry singleton.
161
+ * Lazily loads from settings.json on first access.
162
+ */
163
+ export declare function getModelRegistry(): ModelRegistry;
164
+ /**
165
+ * Reset the global singleton (for testing or hot-reload).
166
+ */
167
+ export declare function resetModelRegistry(): void;
168
+ /**
169
+ * Derive which purposes a model supports from its ModelInfo metadata.
170
+ * Layer 1: ModelCatalog (models.dev) modalities → purpose mapping.
171
+ *
172
+ * Priority: mediaType field → vision field → fallback to textGeneration.
173
+ */
174
+ export declare function deriveModelPurposes(model: ModelInfo): ModelPurpose[];
175
+ /**
176
+ * Layer 3: Name-based heuristic for models not in ModelCatalog or builtin-providers.
177
+ */
178
+ export declare function heuristicModelPurposes(modelId: string): ModelPurpose[];
179
+ /**
180
+ * Refresh models from ModelCatalog (remote models.dev + disk cache) for given providers.
181
+ * Merges discovered models into the registry without overwriting user-modified entries.
182
+ */
183
+ export declare function refreshModelsFromCatalog(registry: ModelRegistry, providerIds: string[]): void;
184
+ /**
185
+ * Force refresh the ModelCatalog from remote, then merge into registry.
186
+ */
187
+ export declare function forceRefreshCatalog(registry: ModelRegistry, providerIds: string[]): Promise<boolean>;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * ProjectInstructionsStore — CRUD for project-scoped instruction files.
2
+ * ProjectInstructionsStore — CRUD for project-scoped rule/instruction files.
3
3
  *
4
- * Storage location: `<workspace>/.qlogicagent/instructions/*.md`
5
- * Format matches Gateway's InstructionsStore output for seamless migration.
4
+ * Storage location: `<workspace>/.qlogicagent/rules/*.md`
5
+ * Unified directory for all project instructions and rules.
6
6
  */
7
7
  export interface InstructionFile {
8
8
  filename: string;
@@ -12,10 +12,12 @@ export declare function createProject(params: {
12
12
  workspaceDir: string;
13
13
  type?: ProjectType;
14
14
  groupId?: string;
15
+ skipAutoSwitch?: boolean;
15
16
  }): ProjectInfo;
16
17
  export declare function listProjects(): ProjectInfo[];
17
18
  export declare function getActiveProject(): ProjectInfo | null;
18
19
  export declare function getProjectById(projectId: string): ProjectInfo | null;
20
+ export declare function updateProject(projectId: string, patch: Partial<Pick<ProjectInfo, "planStatus" | "planAgents" | "planWinnerId" | "leaderSessionId">>): boolean;
19
21
  export declare function switchProject(projectId: string): ProjectInfo | null;
20
22
  export declare function deleteProject(projectId: string): {
21
23
  deleted: boolean;
@@ -23,6 +25,7 @@ export declare function deleteProject(projectId: string): {
23
25
  };
24
26
  export declare function getOrCreateDefaultProject(defaultWorkspaceDir: string): ProjectInfo;
25
27
  export declare function renameProject(projectId: string, newName: string): ProjectInfo | null;
28
+ export declare function updateProjectWorkspaceDir(projectId: string, newDir: string): boolean;
26
29
  export declare function archiveProject(projectId: string): {
27
30
  archived: boolean;
28
31
  switchedTo?: ProjectInfo;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Sub-agent Token Budget Enforcer 鈥?CC-aligned budget limits.
2
+ * Sub-agent Token Budget EnforcerCC-aligned budget limits.
3
3
  *
4
4
  * Prevents sub-agents from consuming infinite tokens by:
5
5
  * 1. Per-task token budget (from TaskStateBase.tokenBudget)
@@ -7,7 +7,7 @@
7
7
  * 3. Budget continuation messages (CC tokenBudget.ts pattern)
8
8
  * 4. Graceful degradation (warn 鈫?force-stop, never hard-crash)
9
9
  *
10
- * CC reference: utils/tokenBudget.ts, main.tsx --max-budget-usd / --task-budget
10
+ * CC reference: utils/tokenBudget.ts, main.tsxmax-budget-usd /task-budget
11
11
  *
12
12
  * Key difference from CC: We track prompt + completion tokens (not USD).
13
13
  * CC has no explicit per-sub-agent budget; they rely on session-level maxBudgetUsd.
@@ -6,7 +6,7 @@
6
6
  * Implements the host-provided git worktree backend:
7
7
  * - enterWorktree(): git worktree add -B <branch> <path> HEAD
8
8
  * - exitWorktree(): git worktree remove / keep
9
- * - listWorktrees(): git worktree list --porcelain
9
+ * - listWorktrees(): git worktree listporcelain
10
10
  * - isInWorktree(): check if cwd is inside a worktree
11
11
  * - currentWorktree(): get current worktree info
12
12
  *
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Pet module — barrel export.
3
+ */
4
+ export { PetSoulService, type PetSoul, type PetStats, type PetBreed } from "./pet-soul-service.js";
5
+ export { maybeGenerateReaction, generateLLMReaction, type ReactionPool, type LLMReactionContext, type ReactionStyle } from "./pet-reaction-service.js";
6
+ export { petContextInjection } from "./pet-context-injection.js";
7
+ export { PetGrowthEngine, type GrowthEvent, type MoltResult, type PetAbility } from "./pet-growth-engine.js";
8
+ export { loadPetFile, validatePetManifest, sanitizeSvg, type PetManifest, type PetFileBundle } from "./pet-file-loader.js";
@@ -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>;