qlogicagent 2.7.0 → 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 (115) hide show
  1. package/dist/agent.js +18 -18
  2. package/dist/cli.js +353 -413
  3. package/dist/index.js +373 -433
  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 +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 +64 -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 +77 -4
  35. package/dist/types/protocol/wire/index.d.ts +1 -1
  36. package/dist/types/protocol/wire/notification-payloads.d.ts +72 -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 +8 -0
  55. package/dist/types/runtime/pet/pet-context-injection.d.ts +8 -0
  56. package/dist/types/runtime/pet/pet-file-loader.d.ts +62 -0
  57. package/dist/types/runtime/pet/pet-growth-engine.d.ts +60 -0
  58. package/dist/types/runtime/pet/pet-reaction-service.d.ts +33 -0
  59. package/dist/types/runtime/pet/pet-soul-service.d.ts +71 -0
  60. package/dist/types/runtime/session/group-session-split.d.ts +38 -0
  61. package/dist/types/runtime/session/index.d.ts +4 -2
  62. package/dist/types/runtime/session/session-locator.d.ts +24 -0
  63. package/dist/types/runtime/session/session-memory.d.ts +4 -4
  64. package/dist/types/runtime/session/session-persistence.d.ts +47 -46
  65. package/dist/types/runtime/session/session-state.d.ts +3 -5
  66. package/dist/types/skills/memory/local-memory-provider.d.ts +1 -1
  67. package/dist/types/skills/memory/local-store.d.ts +3 -2
  68. package/dist/types/skills/memory/memdir.d.ts +7 -4
  69. package/dist/types/skills/memory/memory-provider-factory.d.ts +2 -8
  70. package/dist/types/skills/permissions/denial-audit-log.d.ts +1 -1
  71. package/dist/types/skills/permissions/permission-classifier.d.ts +1 -1
  72. package/dist/types/skills/tools/search-tool.d.ts +1 -1
  73. package/dist/types/skills/tools.d.ts +3 -3
  74. package/dist/types/transport/acp-event-emitter.d.ts +1 -1
  75. package/dist/types/transport/acp-server.d.ts +2 -2
  76. package/package.json +2 -1
  77. package/dist/types/llm/adapters/aliyun-oss-file-upload-adapter.d.ts +0 -44
  78. package/dist/types/llm/adapters/gemini-file-upload-adapter.d.ts +0 -26
  79. package/dist/types/llm/adapters/hub-oss-file-upload-adapter.d.ts +0 -29
  80. package/dist/types/llm/adapters/index.d.ts +0 -10
  81. package/dist/types/llm/adapters/openai-file-upload-adapter.d.ts +0 -38
  82. package/dist/types/llm/adapters/volcengine-file-upload-adapter.d.ts +0 -24
  83. package/dist/types/llm/builtin-providers.d.ts +0 -10
  84. package/dist/types/llm/debug-transport.d.ts +0 -12
  85. package/dist/types/llm/file-upload-service.d.ts +0 -68
  86. package/dist/types/llm/gemini-schema-utils.d.ts +0 -17
  87. package/dist/types/llm/llm-client.d.ts +0 -43
  88. package/dist/types/llm/media-client.d.ts +0 -42
  89. package/dist/types/llm/media-transport.d.ts +0 -176
  90. package/dist/types/llm/model-catalog.d.ts +0 -82
  91. package/dist/types/llm/model-detection.d.ts +0 -22
  92. package/dist/types/llm/provider-def.d.ts +0 -203
  93. package/dist/types/llm/provider-registry.d.ts +0 -59
  94. package/dist/types/llm/provider-tool-api.d.ts +0 -44
  95. package/dist/types/llm/retry.d.ts +0 -37
  96. package/dist/types/llm/transport.d.ts +0 -281
  97. package/dist/types/llm/transports/anthropic-messages.d.ts +0 -65
  98. package/dist/types/llm/transports/gemini-cache-api.d.ts +0 -86
  99. package/dist/types/llm/transports/gemini-file-api.d.ts +0 -90
  100. package/dist/types/llm/transports/gemini-generatecontent.d.ts +0 -56
  101. package/dist/types/llm/transports/gemini-lyria-realtime.d.ts +0 -117
  102. package/dist/types/llm/transports/gemini-media.d.ts +0 -53
  103. package/dist/types/llm/transports/media-resolve.d.ts +0 -50
  104. package/dist/types/llm/transports/minimax-media.d.ts +0 -55
  105. package/dist/types/llm/transports/openai-chat.d.ts +0 -81
  106. package/dist/types/llm/transports/openai-media.d.ts +0 -24
  107. package/dist/types/llm/transports/openai-responses.d.ts +0 -63
  108. package/dist/types/llm/transports/qwen-media.d.ts +0 -50
  109. package/dist/types/llm/transports/realtime-transport.d.ts +0 -183
  110. package/dist/types/llm/transports/volcengine-grounding.d.ts +0 -58
  111. package/dist/types/llm/transports/volcengine-media.d.ts +0 -93
  112. package/dist/types/llm/transports/volcengine-responses.d.ts +0 -64
  113. package/dist/types/llm/transports/zhipu-media.d.ts +0 -82
  114. package/dist/types/llm/transports/zhipu-tool-api.d.ts +0 -35
  115. package/dist/types/runtime/infra/project-plan-store.d.ts +0 -27
@@ -9,10 +9,12 @@
9
9
  export declare const AGENT_DOT_DIR = ".qlogicagent";
10
10
  /** `~/.qlogicagent/` (or QLOGICAGENT_HOME override) */
11
11
  export declare function getUserAgentHome(): string;
12
- /** `~/.qlogicagent/sessions/` */
13
- export declare function getUserSessionsRoot(): string;
14
- /** `~/.qlogicagent/sessions/{sessionId}` */
15
- export declare function getUserSessionDir(sessionId: string): string;
12
+ /**
13
+ * Ensure the user agent home directory exists and is writable.
14
+ * Returns the path if accessible, throws with a friendly message otherwise.
15
+ * Call this once at startup rather than on every path resolution.
16
+ */
17
+ export declare function ensureUserAgentHome(): string;
16
18
  /** `~/.qlogicagent/.credentials.json` */
17
19
  export declare function getUserCredentialsPath(): string;
18
20
  /** `~/.qlogicagent/plugins/` */
@@ -25,8 +27,6 @@ export declare function getUserSettingsPath(): string;
25
27
  export declare function getUserCacheDir(): string;
26
28
  /** `~/.qlogicagent/debug-logs/` */
27
29
  export declare function getUserDebugLogsDir(): string;
28
- /** `~/.qlogicagent/checkpoints/` or `~/.qlogicagent/checkpoints/{sessionId}` */
29
- export declare function getUserCheckpointsDir(sessionId?: string): string;
30
30
  /** `~/.qlogicagent/plugin-cache/` */
31
31
  export declare function getUserPluginCacheDir(): string;
32
32
  /** `~/.qlogicagent/mcp.json` */
@@ -39,26 +39,20 @@ export declare function getUserWorkflowsDir(): string;
39
39
  export declare function getUserInstructionsPath(): string;
40
40
  /** `~/.qlogicagent/rules/` */
41
41
  export declare function getUserRulesDir(): string;
42
- /** `~/.qlogicagent/media/` — auto-downloaded media files (images, videos, audio). */
43
- export declare function getUserMediaDir(): string;
44
42
  /** `<cwd>/.qlogicagent/` */
45
- export declare function getProjectAgentDir(cwd?: string): string;
43
+ export declare function getProjectAgentDir(cwd: string): string;
46
44
  /** `<cwd>/.qlogicagent/workflows/` */
47
- export declare function getProjectWorkflowsDir(cwd?: string): string;
45
+ export declare function getProjectWorkflowsDir(cwd: string): string;
48
46
  /** `<cwd>/.qlogicagent/plugins/` */
49
- export declare function getProjectPluginsDir(cwd?: string): string;
47
+ export declare function getProjectPluginsDir(cwd: string): string;
50
48
  /** `<cwd>/.qlogicagent/skills/` */
51
- export declare function getProjectSkillsDir(cwd?: string): string;
49
+ export declare function getProjectSkillsDir(cwd: string): string;
52
50
  /** `<cwd>/.qlogicagent/settings.json` */
53
- export declare function getProjectSettingsPath(cwd?: string): string;
51
+ export declare function getProjectSettingsPath(cwd: string): string;
54
52
  /** `<cwd>/.qlogicagent/INSTRUCTIONS.md` */
55
- export declare function getProjectInstructionsPath(cwd?: string): string;
56
- /** `<cwd>/.qlogicagent/instructions/` — project-scoped instruction files (CRUD via RPC) */
57
- export declare function getProjectInstructionsDir(cwd?: string): string;
58
- /** `<cwd>/.qlogicagent/plans/` — project-scoped plan files */
59
- export declare function getProjectPlansDir(cwd?: string): string;
60
- /** `<cwd>/.qlogicagent/rules/` */
61
- export declare function getProjectRulesDir(cwd?: string): string;
53
+ export declare function getProjectInstructionsPath(cwd: string): string;
54
+ /** `<cwd>/.qlogicagent/rules/` — unified rules + instructions directory */
55
+ export declare function getProjectRulesDir(cwd: string): string;
62
56
  /** `<cwd>/.qlogicagent/sessions/` */
63
57
  export declare function getProjectSessionsRoot(cwd: string): string;
64
58
  /** `<cwd>/.qlogicagent/sessions/{sessionId}` */
@@ -68,16 +62,19 @@ export declare function getProjectCheckpointsDir(cwd: string, sessionId?: string
68
62
  /** `<gitRoot>/.qlogicagent/hooks/` */
69
63
  export declare function getGitRootHooksDir(gitRoot: string): string;
70
64
  /**
71
- * Discover all known project directories from session history.
72
- * Scans `~/.qlogicagent/sessions/` metadata to extract unique `cwd` paths.
65
+ * Discover all known project directories from the project store.
73
66
  * Used for cross-project skill recall (read-only, never writes to foreign projects).
74
67
  *
68
+ * NOTE: Does NOT import project-store directly to avoid circular deps.
69
+ * Caller must pass the project list.
70
+ *
71
+ * @param projectDirs - All known project workspace directories
75
72
  * @param excludeCwd - Current project cwd to exclude from results
76
- * @returns Array of absolute paths to project roots that have been worked on
73
+ * @returns Array of absolute paths to project roots that have skill directories
77
74
  */
78
- export declare function getKnownProjectDirs(excludeCwd?: string): string[];
75
+ export declare function getKnownProjectDirs(projectDirs: string[], excludeCwd?: string): string[];
79
76
  /**
80
77
  * Get skill directories from all known projects (excluding current).
81
78
  * Returns paths to `<project>/.qlogicagent/skills/` for recall-only access.
82
79
  */
83
- export declare function getAllProjectSkillDirs(excludeCwd?: string): string[];
80
+ export declare function getAllProjectSkillDirs(projectDirs: string[], excludeCwd?: string): string[];
@@ -7,7 +7,7 @@
7
7
  * - Own memory + tool context (no shared process.cwd)
8
8
  * - Lifecycle tracking (PID, health, abort)
9
9
  *
10
- * CC does this via tmux split-pane + `claude --agent-id ...` commands.
10
+ * CC does this via tmux split-pane + `claudeagent-id ...` commands.
11
11
  * We spawn `node dist/cli.js` as child processes with JSON-RPC stdio.
12
12
  *
13
13
  * Reference: claude-code-haha/src/utils/swarm/spawnMultiAgent.ts
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Supported provider metadata for settings RPC.
3
+ *
4
+ * Bridges provider-core's BUILTIN_PROVIDERS into the ModelPurpose system.
5
+ * This is the authoritative list of providers shown in "Add Key" UI.
6
+ *
7
+ * IMPORTANT: Model lists here are the Layer 2 (offline fallback) data source.
8
+ * Layer 1 is ModelCatalog (models.dev remote). These two are the ONLY sources.
9
+ */
10
+ import type { ModelPurpose } from "./model-registry.js";
11
+ export interface KnownModelMeta {
12
+ model: string;
13
+ displayName: string;
14
+ purposes: ModelPurpose[];
15
+ baseUrl?: string;
16
+ }
17
+ export interface SupportedProviderMeta {
18
+ id: string;
19
+ displayName: string;
20
+ baseUrl: string;
21
+ defaultRateLimit?: {
22
+ rpm?: number;
23
+ tpm?: number;
24
+ };
25
+ knownModels: KnownModelMeta[];
26
+ }
27
+ /**
28
+ * Minimal offline fallback providers.
29
+ * Remote catalog (Layer 1) has text generation models; this Layer 2 keeps ONLY
30
+ * specialized models that remote may not cover: embedding, TTS, STT, image gen,
31
+ * video gen, music gen, 3D gen, realtime voice/video, voice clone.
32
+ *
33
+ * All providers are kept (for Add Key UI dropdown + baseUrl lookup).
34
+ * Text generation / image understanding models are NOT listed here — remote always has them.
35
+ */
36
+ export declare const SUPPORTED_PROVIDERS: SupportedProviderMeta[];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Local Checkpoint Backend — git-based shadow repo implementation.
3
3
  *
4
- * Creates and manages checkpoint snapshots in `~/.qlogicagent/checkpoints/<sessionId>/`
4
+ * Creates and manages checkpoint snapshots in `<project>/.qlogicagent/checkpoints/<sessionId>/`
5
5
  * using a shadow git repository independent of the user's project .git.
6
6
  */
7
7
  import type { CheckpointToolDeps } from "../../skills/tools/checkpoint-tool.js";
@@ -1,8 +1,7 @@
1
- export { AGENT_DOT_DIR, getUserAgentHome, getUserSessionDir, getUserCredentialsPath, getUserPluginsDir, getUserSkillsDir, getUserSettingsPath, getUserCacheDir, getUserDebugLogsDir, getUserCheckpointsDir, getUserPluginCacheDir, getUserMcpConfigPath, getUserMarketplaceConfigPath, getUserWorkflowsDir, getUserInstructionsPath, getProjectAgentDir, getProjectWorkflowsDir, getProjectPluginsDir, getProjectSkillsDir, getProjectSettingsPath, getProjectInstructionsPath, getProjectInstructionsDir, getProjectPlansDir, getProjectRulesDir, getGitRootHooksDir, getKnownProjectDirs, getAllProjectSkillDirs, } from "./agent-paths.js";
1
+ export { AGENT_DOT_DIR, getUserAgentHome, getUserCredentialsPath, getUserPluginsDir, getUserSkillsDir, getUserSettingsPath, getUserCacheDir, getUserDebugLogsDir, getUserPluginCacheDir, getUserMcpConfigPath, getUserMarketplaceConfigPath, getUserWorkflowsDir, getProjectAgentDir, getProjectWorkflowsDir, getProjectPluginsDir, getProjectSkillsDir, getProjectSettingsPath, getProjectInstructionsPath, getProjectRulesDir, getGitRootHooksDir, getKnownProjectDirs, getAllProjectSkillDirs, } from "./agent-paths.js";
2
2
  export { getBudgetContinuationMessage } from "./token-budget.js";
3
3
  export { type SecureStorage, saveApiKey, loadApiKey } from "./secure-storage.js";
4
4
  export { ProjectInstructionsStore, type InstructionFile } from "./project-instructions-store.js";
5
- export { ProjectPlanStore, type PlanEntry } from "./project-plan-store.js";
6
5
  export { createFileWatcher, FileWatcher } from "./file-watcher.js";
7
6
  export { TaskStore } from "./task-runtime.js";
8
7
  export { createWorktreeBackend } from "./worktree-backend.js";
@@ -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;