qlogicagent 2.1.0 → 2.2.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 (50) hide show
  1. package/dist/agent.js +7 -7
  2. package/dist/cli.js +223 -206
  3. package/dist/contracts.js +1 -1
  4. package/dist/index.js +222 -205
  5. package/dist/orchestration.js +6 -6
  6. package/dist/types/agent/types.d.ts +3 -1
  7. package/dist/types/cli/stdio-server.d.ts +19 -1
  8. package/dist/types/cli/tool-bootstrap.d.ts +8 -0
  9. package/dist/types/contracts/index.d.ts +0 -1
  10. package/dist/types/contracts/todo.d.ts +8 -21
  11. package/dist/types/llm/adapters/aliyun-oss-file-upload-adapter.d.ts +44 -0
  12. package/dist/types/llm/adapters/gemini-file-upload-adapter.d.ts +26 -0
  13. package/dist/types/llm/adapters/hub-oss-file-upload-adapter.d.ts +29 -0
  14. package/dist/types/llm/adapters/index.d.ts +10 -0
  15. package/dist/types/llm/adapters/openai-file-upload-adapter.d.ts +38 -0
  16. package/dist/types/llm/adapters/volcengine-file-upload-adapter.d.ts +24 -0
  17. package/dist/types/llm/file-upload-service.d.ts +68 -0
  18. package/dist/types/llm/transports/anthropic-messages.d.ts +4 -0
  19. package/dist/types/llm/transports/gemini-generatecontent.d.ts +4 -0
  20. package/dist/types/llm/transports/media-resolve.d.ts +37 -12
  21. package/dist/types/llm/transports/openai-chat.d.ts +4 -0
  22. package/dist/types/llm/transports/openai-responses.d.ts +3 -0
  23. package/dist/types/llm/transports/volcengine-responses.d.ts +4 -0
  24. package/dist/types/orchestration/tool-loop/tool-schema.d.ts +1 -0
  25. package/dist/types/protocol/methods.d.ts +70 -0
  26. package/dist/types/protocol/notifications.d.ts +42 -0
  27. package/dist/types/runtime/execution/dream-category-context.d.ts +1 -1
  28. package/dist/types/runtime/infra/agent-paths.d.ts +6 -0
  29. package/dist/types/runtime/infra/index.d.ts +3 -1
  30. package/dist/types/runtime/infra/media-persistence.d.ts +71 -0
  31. package/dist/types/runtime/infra/project-instructions-store.d.ts +30 -0
  32. package/dist/types/runtime/infra/project-plan-store.d.ts +27 -0
  33. package/dist/types/runtime/infra/project-store.d.ts +30 -0
  34. package/dist/types/skills/index.d.ts +2 -4
  35. package/dist/types/skills/memory/categories.d.ts +5 -0
  36. package/dist/types/skills/memory/memdir.d.ts +6 -1
  37. package/dist/types/skills/memory/recall-category-filter.d.ts +1 -1
  38. package/dist/types/skills/permissions/group-security-policy.d.ts +15 -0
  39. package/dist/types/skills/permissions/index.d.ts +1 -0
  40. package/dist/types/skills/plugins/plugin-loader.d.ts +5 -0
  41. package/dist/types/skills/portable-tool.d.ts +13 -2
  42. package/dist/types/skills/tools/plan-mode-tool.d.ts +1 -1
  43. package/dist/types/skills/tools/read-tool.d.ts +2 -2
  44. package/dist/types/skills/tools/task-tool.d.ts +64 -75
  45. package/package.json +1 -1
  46. package/dist/types/contracts/planner.d.ts +0 -35
  47. package/dist/types/orchestration/error-handling/failover-error.d.ts +0 -33
  48. package/dist/types/skills/memory/memory-write-gate.d.ts +0 -46
  49. package/dist/types/skills/memory/memory-write-hook.d.ts +0 -44
  50. package/dist/types/skills/todo-tool.d.ts +0 -72
@@ -21,6 +21,7 @@
21
21
  */
22
22
  import type { LLMChunk, LLMRequest, LLMTransport } from "../transport.js";
23
23
  import type { ProviderQuirks } from "../provider-def.js";
24
+ import type { FileUploadAdapter } from "../file-upload-service.js";
24
25
  export interface GeminiGenerateContentTransportConfig {
25
26
  /** Base URL, e.g. "https://generativelanguage.googleapis.com/v1beta" */
26
27
  baseUrl: string;
@@ -28,11 +29,14 @@ export interface GeminiGenerateContentTransportConfig {
28
29
  timeoutMs?: number;
29
30
  /** Provider-specific quirks */
30
31
  quirks?: ProviderQuirks;
32
+ /** File upload adapter for resolving local media URLs via upload instead of base64. */
33
+ fileUploadAdapter?: FileUploadAdapter;
31
34
  }
32
35
  export declare class GeminiGenerateContentTransport implements LLMTransport {
33
36
  private baseUrl;
34
37
  private timeoutMs;
35
38
  private quirks;
39
+ private fileUploadAdapter?;
36
40
  constructor(config: GeminiGenerateContentTransportConfig);
37
41
  stream(request: LLMRequest, apiKey: string, signal?: AbortSignal): AsyncGenerator<LLMChunk>;
38
42
  private buildRequestBody;
@@ -1,25 +1,50 @@
1
1
  /**
2
- * Media URL Resolution — converts local/private URLs to inline base64 data URLs.
2
+ * Media URL Resolution — resolves local/private URLs for cloud LLM APIs.
3
3
  *
4
- * Cloud LLM APIs (OpenAI, Anthropic, DeepSeek) cannot fetch content from
5
- * localhost or private networks. This utility detects such URLs and resolves
6
- * them to base64 data URLs that can be sent inline.
4
+ * Cloud LLM APIs (OpenAI, Anthropic, DeepSeek, etc.) cannot fetch content
5
+ * from localhost or private networks.
6
+ *
7
+ * **Primary approach (upload-based):**
8
+ * Local URLs are fetched → uploaded to provider's File API or Aliyun OSS → public URL returned.
9
+ * This is the ONLY approach for images, video, and documents.
10
+ *
11
+ * **Audio exception (base64):**
12
+ * OpenAI's input_audio.data API field mandates base64 encoding.
13
+ * resolveMediaUrl() is retained ONLY for this case.
7
14
  *
8
15
  * URL-first design: the gateway stores media as HTTP URLs; this layer handles
9
16
  * the last-mile transformation before sending to provider APIs.
10
17
  */
18
+ import type { FileUploadAdapter } from "../file-upload-service.js";
11
19
  /** Check if a URL points to a local/private address that cloud APIs cannot reach. */
12
20
  export declare function isLocalUrl(url: string): boolean;
21
+ export interface MediaResolveContext {
22
+ /** Provider-specific upload adapter. */
23
+ uploadAdapter: FileUploadAdapter;
24
+ /** API key for the upload. */
25
+ apiKey: string;
26
+ /** Abort signal. */
27
+ signal?: AbortSignal;
28
+ }
13
29
  /**
14
- * Resolve a URL to a base64 data URL if it's a local address.
15
- * Public URLs are returned as-is (the LLM API can fetch them directly).
30
+ * Resolve a local URL by uploading to the provider's File API.
31
+ * This is the **preferred** method for all media types.
16
32
  *
17
- * Returns the original URL for non-local addresses.
18
- * Returns a `data:<mime>;base64,...` string for local addresses.
33
+ * Public URLs pass through unchanged.
34
+ * Local URLs are uploaded public URL or file_id returned.
19
35
  */
20
- export declare function resolveMediaUrl(url: string, fallbackMime?: string): Promise<string>;
36
+ export declare function resolveMediaUrlViaUpload(url: string, ctx: MediaResolveContext): Promise<string>;
37
+ /**
38
+ * Batch-resolve URLs via upload. Best-effort: failures return original URL.
39
+ */
40
+ export declare function resolveMediaUrlsViaUpload(urls: string[], ctx: MediaResolveContext): Promise<string[]>;
21
41
  /**
22
- * Batch-resolve multiple URLs. Returns array in same order.
23
- * Failures are logged and the original URL is kept (best-effort).
42
+ * Resolve local audio URL to base64 data URL.
43
+ *
44
+ * ONLY for audio — OpenAI's input_audio.data API field mandates base64 encoding.
45
+ * There is no upload alternative for audio in the OpenAI API.
46
+ *
47
+ * For images/video/documents: ALWAYS use resolveMediaUrlViaUpload() instead.
48
+ * base64 is forbidden for non-audio media per project architecture rules.
24
49
  */
25
- export declare function resolveMediaUrls(urls: string[], fallbackMime?: string): Promise<string[]>;
50
+ export declare function resolveMediaUrl(url: string, fallbackMime?: string): Promise<string>;
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import type { LLMChunk, LLMRequest, LLMTransport, FIMRequest, FIMChunk } from "../transport.js";
15
15
  import type { ProviderQuirks } from "../provider-def.js";
16
+ import type { FileUploadAdapter } from "../file-upload-service.js";
16
17
  export interface OpenAIChatTransportConfig {
17
18
  baseUrl: string;
18
19
  /** Additional headers (e.g. for specific providers) */
@@ -25,6 +26,8 @@ export interface OpenAIChatTransportConfig {
25
26
  omitZeroTemperature?: boolean;
26
27
  /** Provider-specific quirks (CC/altcode parity) */
27
28
  quirks?: ProviderQuirks;
29
+ /** File upload adapter for resolving local media URLs via upload instead of base64. */
30
+ fileUploadAdapter?: FileUploadAdapter;
28
31
  }
29
32
  export declare class OpenAIChatTransport implements LLMTransport {
30
33
  private baseUrl;
@@ -33,6 +36,7 @@ export declare class OpenAIChatTransport implements LLMTransport {
33
36
  private supportsStreamOptions;
34
37
  private omitZeroTemperature;
35
38
  private quirks;
39
+ private fileUploadAdapter?;
36
40
  private cumulativeReasoningLen;
37
41
  private cumulativeContentLen;
38
42
  constructor(config: OpenAIChatTransportConfig);
@@ -25,17 +25,20 @@
25
25
  */
26
26
  import type { LLMChunk, LLMRequest, LLMTransport } from "../transport.js";
27
27
  import type { ProviderQuirks } from "../provider-def.js";
28
+ import type { FileUploadAdapter } from "../file-upload-service.js";
28
29
  export interface OpenAIResponsesTransportConfig {
29
30
  baseUrl: string;
30
31
  extraHeaders?: Record<string, string>;
31
32
  timeoutMs?: number;
32
33
  quirks?: ProviderQuirks;
34
+ fileUploadAdapter?: FileUploadAdapter;
33
35
  }
34
36
  export declare class OpenAIResponsesTransport implements LLMTransport {
35
37
  private baseUrl;
36
38
  private extraHeaders;
37
39
  private timeoutMs;
38
40
  private quirks;
41
+ private fileUploadAdapter?;
39
42
  constructor(config: OpenAIResponsesTransportConfig);
40
43
  stream(request: LLMRequest, apiKey: string, signal?: AbortSignal): AsyncGenerator<LLMChunk>;
41
44
  private buildRequestBody;
@@ -18,17 +18,21 @@
18
18
  */
19
19
  import type { LLMChunk, LLMRequest, LLMTransport } from "../transport.js";
20
20
  import type { ProviderQuirks } from "../provider-def.js";
21
+ import type { FileUploadAdapter } from "../file-upload-service.js";
21
22
  export interface VolcengineResponsesTransportConfig {
22
23
  baseUrl: string;
23
24
  extraHeaders?: Record<string, string>;
24
25
  timeoutMs?: number;
25
26
  quirks?: ProviderQuirks;
27
+ /** File upload adapter for resolving local media URLs via upload instead of base64. */
28
+ fileUploadAdapter?: FileUploadAdapter;
26
29
  }
27
30
  export declare class VolcengineResponsesTransport implements LLMTransport {
28
31
  private baseUrl;
29
32
  private extraHeaders;
30
33
  private timeoutMs;
31
34
  private quirks;
35
+ private fileUploadAdapter?;
32
36
  constructor(config: VolcengineResponsesTransportConfig);
33
37
  stream(request: LLMRequest, apiKey: string, signal?: AbortSignal): AsyncGenerator<LLMChunk>;
34
38
  /**
@@ -38,5 +38,6 @@ export declare function buildToolResultMessage(callId: string, result: {
38
38
  payload?: unknown;
39
39
  error?: string;
40
40
  toolReferences?: string[];
41
+ imageUrls?: string[];
41
42
  }): Record<string, unknown>;
42
43
  export declare function cleanToolSchemaForGemini(schema: Record<string, unknown>): unknown;
@@ -302,6 +302,56 @@ export interface TasksCancelResult {
302
302
  ok: boolean;
303
303
  message: string;
304
304
  }
305
+ export type ProjectType = "default" | "personal" | "group";
306
+ export type ProjectStatus = "active" | "archived";
307
+ export interface ProjectInfo {
308
+ id: string;
309
+ name: string;
310
+ workspaceDir: string;
311
+ type: ProjectType;
312
+ status: ProjectStatus;
313
+ groupId?: string;
314
+ createdAt: string;
315
+ updatedAt: string;
316
+ }
317
+ export interface ProjectCreateParams {
318
+ name: string;
319
+ workspaceDir: string;
320
+ type?: ProjectType;
321
+ groupId?: string;
322
+ }
323
+ export interface ProjectCreateResult {
324
+ ok: boolean;
325
+ project: ProjectInfo;
326
+ }
327
+ export interface ProjectListParams {
328
+ }
329
+ export interface ProjectListResult {
330
+ projects: ProjectInfo[];
331
+ }
332
+ export interface ProjectDeleteParams {
333
+ projectId: string;
334
+ }
335
+ export interface ProjectDeleteResult {
336
+ ok: boolean;
337
+ switchedTo?: ProjectInfo;
338
+ }
339
+ export interface SessionSwitchProjectParams {
340
+ projectId?: string;
341
+ projectName?: string;
342
+ workspaceDir?: string;
343
+ }
344
+ export interface SessionSwitchProjectResult {
345
+ ok: boolean;
346
+ project: ProjectInfo;
347
+ }
348
+ export interface SessionGetStateParams {
349
+ }
350
+ export interface SessionGetStateResult {
351
+ sessionId: string;
352
+ activeProject: ProjectInfo | null;
353
+ projects: ProjectInfo[];
354
+ }
305
355
  export interface RpcMethodMap {
306
356
  "initialize": {
307
357
  params: InitializeParams;
@@ -484,6 +534,26 @@ export interface RpcMethodMap {
484
534
  params: undefined;
485
535
  result: ProductSummary[];
486
536
  };
537
+ "project.create": {
538
+ params: ProjectCreateParams;
539
+ result: ProjectCreateResult;
540
+ };
541
+ "project.list": {
542
+ params: ProjectListParams;
543
+ result: ProjectListResult;
544
+ };
545
+ "project.delete": {
546
+ params: ProjectDeleteParams;
547
+ result: ProjectDeleteResult;
548
+ };
549
+ "session.switchProject": {
550
+ params: SessionSwitchProjectParams;
551
+ result: SessionSwitchProjectResult;
552
+ };
553
+ "session.getState": {
554
+ params: SessionGetStateParams;
555
+ result: SessionGetStateResult;
556
+ };
487
557
  }
488
558
  /** All known RPC method names. */
489
559
  export type RpcMethod = keyof RpcMethodMap;
@@ -192,6 +192,16 @@ export interface TurnMediaProgressNotification {
192
192
  /** Provider id. */
193
193
  provider?: string;
194
194
  }
195
+ /** Media files auto-downloaded to local storage (~/.qlogicagent/media/). */
196
+ export interface TurnMediaPersistedNotification {
197
+ turnId: string;
198
+ files: Array<{
199
+ remoteUrl: string;
200
+ localPath: string;
201
+ bytes: number;
202
+ mimeType: string;
203
+ }>;
204
+ }
195
205
  /** Full todo list updated — enables DeerFlow-style todo panel sync. */
196
206
  export interface TurnTodosUpdatedNotification {
197
207
  turnId?: string;
@@ -279,6 +289,15 @@ export interface MemoryUpdatedNotification {
279
289
  /** Human-readable summary of what changed. */
280
290
  summary?: string;
281
291
  }
292
+ /** Emitted when importance decay runs after a Dream consolidation. */
293
+ export interface MemoryDecayCompletedNotification {
294
+ /** Number of memories whose importance was reduced. */
295
+ decayed: number;
296
+ /** Number of memories archived (below threshold). */
297
+ archived: number;
298
+ /** Duration in ms. */
299
+ durationMs: number;
300
+ }
282
301
  /** Session metadata changed (title, model, etc.). */
283
302
  export interface SessionInfoNotification {
284
303
  sessionId: string;
@@ -407,6 +426,24 @@ export interface ProductCompletedNotification {
407
426
  productId: string;
408
427
  summary: string;
409
428
  }
429
+ /** A project was created. */
430
+ export interface ProjectCreatedNotification {
431
+ id: string;
432
+ name: string;
433
+ workspaceDir: string;
434
+ type: string;
435
+ groupId?: string;
436
+ }
437
+ /** Active project was switched. */
438
+ export interface ProjectSwitchedNotification {
439
+ id: string;
440
+ name: string;
441
+ workspaceDir: string;
442
+ }
443
+ /** A project was deleted. */
444
+ export interface ProjectDeletedNotification {
445
+ id: string;
446
+ }
410
447
  export interface NotificationMethodMap {
411
448
  "turn.start": TurnStartNotification;
412
449
  "turn.delta": TurnDeltaNotification;
@@ -425,6 +462,7 @@ export interface NotificationMethodMap {
425
462
  "turn.annotations": TurnAnnotationsNotification;
426
463
  "turn.media_result": TurnMediaResultNotification;
427
464
  "turn.media_progress": TurnMediaProgressNotification;
465
+ "turn.media_persisted": TurnMediaPersistedNotification;
428
466
  "turn.todos_updated": TurnTodosUpdatedNotification;
429
467
  "task.updated": TaskUpdatedNotification;
430
468
  "turn.exec_progress": TurnExecProgressNotification;
@@ -435,6 +473,7 @@ export interface NotificationMethodMap {
435
473
  "turn.skill_instruction": TurnSkillInstructionNotification;
436
474
  "turn.ask_user": TurnAskUserNotification;
437
475
  "memory.updated": MemoryUpdatedNotification;
476
+ "memory.decay.completed": MemoryDecayCompletedNotification;
438
477
  "session.info": SessionInfoNotification;
439
478
  "permission.rule_updated": PermissionRuleUpdatedNotification;
440
479
  "team.updated": TeamUpdatedNotification;
@@ -453,6 +492,9 @@ export interface NotificationMethodMap {
453
492
  "product.checkpointed": ProductCheckpointedNotification;
454
493
  "product.budgetWarning": ProductBudgetWarningNotification;
455
494
  "product.completed": ProductCompletedNotification;
495
+ "project.created": ProjectCreatedNotification;
496
+ "project.switched": ProjectSwitchedNotification;
497
+ "project.deleted": ProjectDeletedNotification;
456
498
  }
457
499
  /** All known notification method names. */
458
500
  export type NotificationMethod = keyof NotificationMethodMap;
@@ -1,4 +1,4 @@
1
- import type { QMemoryCategory } from "../../skills/memory/memory-write-gate.js";
1
+ import type { QMemoryCategory } from "../../skills/memory/categories.js";
2
2
  /** A memory file with its inferred category and metadata. */
3
3
  export interface CategorizedMemoryFile {
4
4
  filename: string;
@@ -39,6 +39,8 @@ 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;
42
44
  /** `<cwd>/.qlogicagent/` */
43
45
  export declare function getProjectAgentDir(cwd?: string): string;
44
46
  /** `<cwd>/.qlogicagent/workflows/` */
@@ -51,6 +53,10 @@ export declare function getProjectSkillsDir(cwd?: string): string;
51
53
  export declare function getProjectSettingsPath(cwd?: string): string;
52
54
  /** `<cwd>/.qlogicagent/INSTRUCTIONS.md` */
53
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;
54
60
  /** `<cwd>/.qlogicagent/rules/` */
55
61
  export declare function getProjectRulesDir(cwd?: string): string;
56
62
  /** `<cwd>/.qlogicagent/sessions/` */
@@ -1,6 +1,8 @@
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, getProjectRulesDir, getGitRootHooksDir, getKnownProjectDirs, getAllProjectSkillDirs, } from "./agent-paths.js";
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";
2
2
  export { getBudgetContinuationMessage } from "./token-budget.js";
3
3
  export { type SecureStorage, saveApiKey, loadApiKey } from "./secure-storage.js";
4
+ export { ProjectInstructionsStore, type InstructionFile } from "./project-instructions-store.js";
5
+ export { ProjectPlanStore, type PlanEntry } from "./project-plan-store.js";
4
6
  export { createFileWatcher, FileWatcher } from "./file-watcher.js";
5
7
  export { TaskStore } from "./task-runtime.js";
6
8
  export { createWorktreeBackend } from "./worktree-backend.js";
@@ -0,0 +1,71 @@
1
+ /**
2
+ * MediaPersistence — Auto-download generated media to local storage.
3
+ *
4
+ * When LLM tools generate files (images, videos, audio) and return
5
+ * cloud URLs, this service downloads them to a persistent local directory
6
+ * so the user can access them offline without manual intervention.
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
14
+ *
15
+ * Integration:
16
+ * Called from the tool result pipeline in tool-loop.ts.
17
+ * When a tool result's `details.mediaUrls` contains URLs,
18
+ * each URL is downloaded and the local path is added to details.
19
+ */
20
+ export interface MediaDownloadResult {
21
+ /** Original cloud URL. */
22
+ remoteUrl: string;
23
+ /** Local file path after download. */
24
+ localPath: string;
25
+ /** File size in bytes. */
26
+ bytes: number;
27
+ /** MIME type (from Content-Type header). */
28
+ mimeType: string;
29
+ }
30
+ export interface MediaPersistenceConfig {
31
+ /**
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.
35
+ */
36
+ projectDir?: string;
37
+ /** Base directory for media storage. Default: ~/.qlogicagent/media/ (fallback only). */
38
+ mediaDir?: string;
39
+ /** Maximum file size to download (bytes). Default: 500MB. */
40
+ maxFileSize?: number;
41
+ /** Download timeout per file (ms). Default: 300_000 (5 min). */
42
+ timeoutMs?: number;
43
+ }
44
+ export declare class MediaPersistence {
45
+ private mediaDir;
46
+ private readonly maxFileSize;
47
+ private readonly timeoutMs;
48
+ constructor(config?: MediaPersistenceConfig);
49
+ /** Update media directory to use a specific project root. */
50
+ setProjectDir(projectDir: string): void;
51
+ /**
52
+ * Download a remote URL to local storage.
53
+ * Returns the local file path and metadata.
54
+ */
55
+ download(remoteUrl: string, hint?: {
56
+ type?: string;
57
+ sessionId?: string;
58
+ }): Promise<MediaDownloadResult>;
59
+ /**
60
+ * Download multiple URLs. Returns results for successful downloads.
61
+ * Failed downloads are logged but don't throw.
62
+ */
63
+ downloadAll(urls: string[], hint?: {
64
+ type?: string;
65
+ sessionId?: string;
66
+ }, log?: {
67
+ warn: (msg: string) => void;
68
+ }): Promise<MediaDownloadResult[]>;
69
+ /** Get the base media directory path. */
70
+ getMediaDir(): string;
71
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * ProjectInstructionsStore — CRUD for project-scoped instruction files.
3
+ *
4
+ * Storage location: `<workspace>/.qlogicagent/instructions/*.md`
5
+ * Format matches Gateway's InstructionsStore output for seamless migration.
6
+ */
7
+ export interface InstructionFile {
8
+ filename: string;
9
+ content: string;
10
+ sizeBytes: number;
11
+ }
12
+ export declare class ProjectInstructionsStore {
13
+ private dir;
14
+ constructor(cwd: string);
15
+ /** List all instruction files for the project. */
16
+ list(): InstructionFile[];
17
+ /** Read a single instruction file. */
18
+ read(filename: string): InstructionFile | null;
19
+ /** Write (create or update) an instruction file. */
20
+ write(filename: string, content: string): InstructionFile;
21
+ /** Delete an instruction file. */
22
+ remove(filename: string): boolean;
23
+ /**
24
+ * Load all instruction files and concatenate into a single block
25
+ * for agent system context injection.
26
+ */
27
+ loadAll(): string;
28
+ private isValidFilename;
29
+ private getDirSize;
30
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ProjectPlanStore — CRUD for project-scoped plan files.
3
+ *
4
+ * Storage location: `<workspace>/.qlogicagent/plans/*.md`
5
+ * Each plan is a markdown file with YAML frontmatter (slug, status, timestamps).
6
+ */
7
+ export interface PlanEntry {
8
+ slug: string;
9
+ status: "active" | "completed" | "abandoned";
10
+ content: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }
14
+ export declare class ProjectPlanStore {
15
+ private dir;
16
+ constructor(cwd: string);
17
+ /** List all plans. */
18
+ list(): PlanEntry[];
19
+ /** Load active plans only. */
20
+ loadActive(): PlanEntry[];
21
+ /** Load a single plan by slug. */
22
+ load(slug: string): PlanEntry | null;
23
+ /** Save or update a plan. */
24
+ save(slug: string, content: string): void;
25
+ /** Delete a plan. */
26
+ remove(slug: string): boolean;
27
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Local Project Store — persists project metadata to ~/.qlogicagent/projects.json.
3
+ *
4
+ * This is the Agent-side (runtime authority) project registry.
5
+ * Hub maintains a mirror copy via EventBus → HubSubscriber → hub.persistProject.
6
+ *
7
+ * Direction A: Agent is the source of truth for project state.
8
+ */
9
+ import type { ProjectInfo, ProjectType } from "../../protocol/methods.js";
10
+ export declare function createProject(params: {
11
+ name: string;
12
+ workspaceDir: string;
13
+ type?: ProjectType;
14
+ groupId?: string;
15
+ }): ProjectInfo;
16
+ export declare function listProjects(): ProjectInfo[];
17
+ export declare function getActiveProject(): ProjectInfo | null;
18
+ export declare function getProjectById(projectId: string): ProjectInfo | null;
19
+ export declare function switchProject(projectId: string): ProjectInfo | null;
20
+ export declare function deleteProject(projectId: string): {
21
+ deleted: boolean;
22
+ switchedTo?: ProjectInfo;
23
+ };
24
+ export declare function getOrCreateDefaultProject(defaultWorkspaceDir: string): ProjectInfo;
25
+ export declare function findByGroupId(groupId: string): ProjectInfo | null;
26
+ export declare function archiveByGroupId(groupId: string): {
27
+ archived: boolean;
28
+ projectId?: string;
29
+ switchedTo?: ProjectInfo;
30
+ };
@@ -8,8 +8,6 @@ export { createQMemoryAdapter } from "./memory/qmemory-adapter.js";
8
8
  export type { QMemoryAdapterConfig, QMemoryHealthStatus, ExtractedMemoryItem, DecayOptions, DecayResult } from "./memory/qmemory-adapter.js";
9
9
  export { THINK_TOOL_NAME, THINK_TOOL_SCHEMA, createThinkTool } from "./think-tool.js";
10
10
  export type { ThinkToolParams } from "./think-tool.js";
11
- export { TODO_TOOL_NAME, TODO_TOOL_SCHEMA, TODO_ACTIONS, createTodoTool } from "./todo-tool.js";
12
- export type { TodoToolParams, TodoToolOptions, TodoAction } from "./todo-tool.js";
13
11
  export { READ_TOOL_NAME, READ_TOOL_SCHEMA, createReadTool } from "./tools/read-tool.js";
14
12
  export type { ReadToolParams, ReadToolDeps, ReadResultType } from "./tools/read-tool.js";
15
13
  export { WRITE_TOOL_NAME, WRITE_TOOL_SCHEMA, createWriteTool } from "./tools/write-tool.js";
@@ -54,8 +52,8 @@ export { PATCH_TOOL_NAME, PATCH_TOOL_SCHEMA, createPatchTool, fuzzyFind } from "
54
52
  export type { PatchToolParams, PatchToolDeps, PatchResult, MatchStrategy, MatchResult } from "./tools/patch-tool.js";
55
53
  export { AGENT_TOOL_NAME, AGENT_TOOL_SCHEMA, createAgentTool } from "./tools/agent-tool.js";
56
54
  export type { AgentToolParams, AgentToolDeps, AgentResult } from "./tools/agent-tool.js";
57
- export { TASK_TOOL_NAME, TASK_TOOL_SCHEMA, createTaskTool } from "./tools/task-tool.js";
58
- export type { TaskToolParams, TaskToolDeps, TaskInfo, TaskResult, TaskAction, TaskStatus } from "./tools/task-tool.js";
55
+ export { TASK_TOOL_NAME, TASK_TOOL_SCHEMA, TASK_ACTIONS, createTaskTool, summarizeTaskList } from "./tools/task-tool.js";
56
+ export type { TaskToolParams, TaskToolOptions, TaskToolHooks, TaskItem, TaskListSummary, TaskAction, TaskStatus } from "./tools/task-tool.js";
59
57
  export { REPL_TOOL_NAME, REPL_TOOL_SCHEMA, REPL_HIDES_TOOLS, createReplTool } from "./tools/repl-tool.js";
60
58
  export type { ReplToolParams, ReplToolDeps, ReplPrimitives, ReplExecResult } from "./tools/repl-tool.js";
61
59
  export { BROWSER_TOOL_NAME, BROWSER_TOOL_SCHEMA, createBrowserTool } from "./tools/browser-tool.js";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Memory categories for QMemory writes.
3
+ * Each has different value thresholds and retention policies.
4
+ */
5
+ export type QMemoryCategory = "lesson" | "preference" | "pattern" | "fact" | "decision" | "skill-learning";
@@ -57,8 +57,13 @@ export declare class Memdir {
57
57
  listFiles(): Promise<MemdirFileInfo[]>;
58
58
  /** Create a new topic file. Fails if it already exists. */
59
59
  createFile(name: string, content: string): Promise<MemdirResult>;
60
- /** Write/overwrite a topic file. */
60
+ /** Write/overwrite a topic file. Auto-splits if content > 8KB. */
61
61
  writeFile(name: string, content: string): Promise<MemdirResult>;
62
+ /**
63
+ * Auto-split: write oversized content into numbered part files.
64
+ * e.g. "lesson-docker.md" → "lesson-docker-1.md", "lesson-docker-2.md"
65
+ */
66
+ private writeFileSplit;
62
67
  /** Read a topic file. */
63
68
  readFile(name: string): Promise<{
64
69
  ok: boolean;
@@ -1,4 +1,4 @@
1
- import type { QMemoryCategory } from "../../skills/memory/memory-write-gate.js";
1
+ import type { QMemoryCategory } from "./categories.js";
2
2
  /** Detected query scenario with preferred categories. */
3
3
  export interface RecallCategoryHint {
4
4
  /** Detected scenario label. */
@@ -0,0 +1,15 @@
1
+ import type { PermissionRuleEntry } from "./types.js";
2
+ /**
3
+ * File path patterns considered sensitive — reading/writing these
4
+ * is blocked in group sessions. Used by the file access guard.
5
+ */
6
+ export declare const GROUP_SENSITIVE_FILE_PATTERNS: readonly RegExp[];
7
+ /**
8
+ * Returns the set of permission rules to inject for group sessions.
9
+ * These should be prepended to the rule engine (first-match wins).
10
+ */
11
+ export declare function getGroupSecurityRules(): PermissionRuleEntry[];
12
+ /**
13
+ * Checks if a file path matches sensitive patterns blocked in group mode.
14
+ */
15
+ export declare function isGroupSensitivePath(filePath: string): boolean;
@@ -9,4 +9,5 @@ export { ClassifierCache } from "./classifier-cache.js";
9
9
  export type { CachedClassification } from "./classifier-cache.js";
10
10
  export { watchSettings, loadInitialSettings } from "./settings-watcher.js";
11
11
  export type { SettingsFile, SettingsWatcherDeps } from "./settings-watcher.js";
12
+ export { getGroupSecurityRules, isGroupSensitivePath } from "./group-security-policy.js";
12
13
  export type { PermissionMode, PermissionBehavior, PermissionResult, PermissionRuleEntry, PermissionConfig, PermissionUpdate, PermissionDecisionReason, ToolPermissionCheckInput, ApprovalRequest, ApprovalResponse, } from "./types.js";
@@ -32,6 +32,11 @@ export declare class PluginLoader {
32
32
  * Get list of all loaded plugins.
33
33
  */
34
34
  getLoaded(): LoadedPlugin[];
35
+ /**
36
+ * Discover and load NEW plugins that weren't present during initial loadAll().
37
+ * Call per-turn to pick up newly-created skill directories (铁律 #16).
38
+ */
39
+ discoverNew(): Promise<number>;
35
40
  /**
36
41
  * Re-check activation for plugins whose TTL has expired.
37
42
  * Call this before tool resolution or periodically in the agent loop.
@@ -5,7 +5,12 @@
5
5
  export interface ToolContentBlock {
6
6
  type: "text" | "image";
7
7
  text?: string;
8
- /** base64-encoded image data (only when type === "image") */
8
+ /**
9
+ * base64-encoded image data (only when type === "image").
10
+ * Used by browser screenshots and MCP tools where data is already in memory.
11
+ * The tool invoker promotes these to data-URL imageUrls for transport resolution.
12
+ * For file-based images, prefer returning localPath via PortableToolResult.imageUrls.
13
+ */
9
14
  data?: string;
10
15
  mimeType?: string;
11
16
  }
@@ -16,6 +21,12 @@ export interface PortableToolResult {
16
21
  content: ToolContentBlock[];
17
22
  /** Arbitrary structured metadata for the calling runtime. */
18
23
  details?: Record<string, unknown>;
24
+ /**
25
+ * Local image file paths produced by this tool (e.g. read tool reading an image).
26
+ * Transport layer resolves these via FileUploadAdapter before sending to the LLM.
27
+ * This avoids loading large files into memory as base64.
28
+ */
29
+ imageUrls?: string[];
19
30
  }
20
31
  /**
21
32
  * A runtime-agnostic tool definition.
@@ -23,7 +34,7 @@ export interface PortableToolResult {
23
34
  * @typeParam TParams The expected parameter shape (for TypeScript consumers).
24
35
  */
25
36
  export interface PortableTool<TParams = Record<string, unknown>> {
26
- /** Unique tool name (e.g. "think", "todo", "memory"). */
37
+ /** Unique tool name (e.g. "think", "task", "memory"). */
27
38
  name: string;
28
39
  /** Human-readable label. */
29
40
  label: string;