qlogicagent 2.0.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 (69) hide show
  1. package/README.md +8 -8
  2. package/dist/agent.js +8 -8
  3. package/dist/cli.js +250 -203
  4. package/dist/contracts.js +1 -1
  5. package/dist/index.js +249 -202
  6. package/dist/orchestration.js +6 -6
  7. package/dist/types/agent/types.d.ts +3 -1
  8. package/dist/types/cli/stdio-server.d.ts +27 -8
  9. package/dist/types/cli/tool-bootstrap.d.ts +8 -0
  10. package/dist/types/contracts/hooks.d.ts +3 -0
  11. package/dist/types/contracts/index.d.ts +0 -1
  12. package/dist/types/contracts/todo.d.ts +8 -21
  13. package/dist/types/llm/adapters/aliyun-oss-file-upload-adapter.d.ts +44 -0
  14. package/dist/types/llm/adapters/gemini-file-upload-adapter.d.ts +26 -0
  15. package/dist/types/llm/adapters/hub-oss-file-upload-adapter.d.ts +29 -0
  16. package/dist/types/llm/adapters/index.d.ts +10 -0
  17. package/dist/types/llm/adapters/openai-file-upload-adapter.d.ts +38 -0
  18. package/dist/types/llm/adapters/volcengine-file-upload-adapter.d.ts +24 -0
  19. package/dist/types/llm/file-upload-service.d.ts +68 -0
  20. package/dist/types/llm/transports/anthropic-messages.d.ts +4 -0
  21. package/dist/types/llm/transports/gemini-generatecontent.d.ts +4 -0
  22. package/dist/types/llm/transports/media-resolve.d.ts +50 -0
  23. package/dist/types/llm/transports/openai-chat.d.ts +4 -0
  24. package/dist/types/llm/transports/openai-responses.d.ts +3 -0
  25. package/dist/types/llm/transports/volcengine-responses.d.ts +4 -0
  26. package/dist/types/orchestration/tool-loop/tool-schema.d.ts +1 -0
  27. package/dist/types/protocol/methods.d.ts +70 -0
  28. package/dist/types/protocol/notifications.d.ts +42 -0
  29. package/dist/types/runtime/execution/dream-agent.d.ts +2 -0
  30. package/dist/types/runtime/execution/dream-category-context.d.ts +47 -0
  31. package/dist/types/runtime/execution/dream-category-context.test.d.ts +1 -0
  32. package/dist/types/runtime/execution/index.d.ts +1 -0
  33. package/dist/types/runtime/execution/memory-decay.d.ts +57 -0
  34. package/dist/types/runtime/execution/memory-decay.test.d.ts +1 -0
  35. package/dist/types/runtime/hooks/index.d.ts +1 -0
  36. package/dist/types/runtime/hooks/memory-hooks.d.ts +20 -0
  37. package/dist/types/runtime/hooks/skill-recall-hooks.d.ts +36 -0
  38. package/dist/types/runtime/infra/agent-paths.d.ts +20 -2
  39. package/dist/types/runtime/infra/disk-storage.d.ts +0 -16
  40. package/dist/types/runtime/infra/index.d.ts +4 -2
  41. package/dist/types/runtime/infra/media-persistence.d.ts +71 -0
  42. package/dist/types/runtime/infra/project-instructions-store.d.ts +30 -0
  43. package/dist/types/runtime/infra/project-plan-store.d.ts +27 -0
  44. package/dist/types/runtime/infra/project-store.d.ts +30 -0
  45. package/dist/types/runtime/session/session-persistence.d.ts +3 -1
  46. package/dist/types/skills/index.d.ts +7 -9
  47. package/dist/types/skills/memory/categories.d.ts +5 -0
  48. package/dist/types/skills/memory/find-relevant-memories.d.ts +70 -0
  49. package/dist/types/skills/memory/memdir.d.ts +85 -0
  50. package/dist/types/skills/memory/memory-tool.d.ts +16 -44
  51. package/dist/types/skills/memory/qmemory-adapter.d.ts +12 -0
  52. package/dist/types/skills/memory/recall-category-filter.d.ts +54 -0
  53. package/dist/types/skills/permissions/group-security-policy.d.ts +15 -0
  54. package/dist/types/skills/permissions/index.d.ts +1 -0
  55. package/dist/types/skills/plugins/plugin-loader.d.ts +5 -0
  56. package/dist/types/skills/portable-tool.d.ts +13 -2
  57. package/dist/types/skills/tools/plan-mode-tool.d.ts +1 -1
  58. package/dist/types/skills/tools/read-tool.d.ts +2 -2
  59. package/dist/types/skills/tools/skill-tool.d.ts +16 -3
  60. package/dist/types/skills/tools/task-tool.d.ts +64 -75
  61. package/package.json +1 -1
  62. package/dist/types/contracts/planner.d.ts +0 -35
  63. package/dist/types/orchestration/error-handling/failover-error.d.ts +0 -33
  64. package/dist/types/skills/memory/memory-store.d.ts +0 -86
  65. package/dist/types/skills/todo-tool.d.ts +0 -72
  66. package/dist/types/skills/tools/skill-invoke-tool.d.ts +0 -46
  67. package/dist/types/skills/tools/skill-list-tool.d.ts +0 -33
  68. package/dist/types/skills/tools/skill-manage-tool.d.ts +0 -73
  69. package/dist/types/skills/tools/skill-view-tool.d.ts +0 -37
@@ -4,7 +4,6 @@
4
4
  * Provides:
5
5
  * - Atomic write (tmp + rename) with dir auto-creation
6
6
  * - JSON read/write helpers
7
- * - MemoryStore disk persistence (auto-save on mutation)
8
7
  */
9
8
  /**
10
9
  * Write data atomically: write to a temp file in the same directory,
@@ -19,18 +18,3 @@ export declare function readJsonFile<T = unknown>(filePath: string): Promise<T |
19
18
  * Write a JSON file atomically.
20
19
  */
21
20
  export declare function writeJsonFile(filePath: string, data: unknown): Promise<void>;
22
- /** Path to user-level memory file: `~/.qlogicagent/memory.json` */
23
- export declare function getMemoryFilePath(): string;
24
- export interface PersistedMemory {
25
- memory: string;
26
- user: string;
27
- /** ISO 8601 timestamp of last save. */
28
- savedAt: string;
29
- }
30
- /** Load persisted memory from disk. Returns undefined if no file exists. */
31
- export declare function loadPersistedMemory(): Promise<PersistedMemory | undefined>;
32
- /** Save memory to disk atomically. */
33
- export declare function savePersistedMemory(data: {
34
- memory: string;
35
- user: string;
36
- }): Promise<void>;
@@ -1,11 +1,13 @@
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, } 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";
7
9
  export { registerCleanup, runCleanupFunctions } from "./cleanup-registry.js";
8
- export { atomicWriteFile, readJsonFile, writeJsonFile, loadPersistedMemory, savePersistedMemory, getMemoryFilePath, type PersistedMemory, } from "./disk-storage.js";
10
+ export { atomicWriteFile, readJsonFile, writeJsonFile, } from "./disk-storage.js";
9
11
  export { AcpDetector, ACP_BACKENDS } from "./acp-detector.js";
10
12
  export { AcpProtocolAdapter, type TranslatedNotification, type AcpHostRequestHandler } from "./acp-protocol-adapter.js";
11
13
  export { AcpUsageTracker, type AccumulatedUsage } from "./acp-usage-tracker.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
+ };
@@ -52,8 +52,10 @@ export interface SessionListEntry {
52
52
  /**
53
53
  * Append a message to the session transcript.
54
54
  * Creates the session directory if it doesn't exist.
55
+ * When turnId is provided, it acts as a per-turn boundary marker enabling
56
+ * reconciliation with Gateway's token_usage records.
55
57
  */
56
- export declare function appendMessage(sessionId: string, message: ChatMessage, projectRoot?: string): Promise<void>;
58
+ export declare function appendMessage(sessionId: string, message: ChatMessage, projectRoot?: string, turnId?: string): Promise<void>;
57
59
  /**
58
60
  * Save session state (cost + metadata) atomically.
59
61
  */
@@ -1,15 +1,13 @@
1
1
  export type { PortableTool, PortableToolResult, ToolContentBlock, } from "./portable-tool.js";
2
2
  export { setToolPool, addTool, addTools, removeTool, findTool, hasTool, getToolNames, getToolCount, executeTool, getToolManifest, getTools, activateTool, isToolActivated, clearActivatedTools, AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, filterToolsForAgent, } from "./tools.js";
3
- export { MEMORY_TOOL_NAME, MEMORY_TOOL_MAX_CONTENT_LENGTH, MEMORY_TOOL_ACTIONS, MEMORY_TOOL_SCHEMA, MEMORY_TOOL_DESCRIPTION, MEMORY_TOOL_LABEL, isMemoryContentSafe, executeMemoryTool, } from "./memory/memory-tool.js";
4
- export type { MemoryToolAction, MemoryToolParams, MemoryToolResult, MemoryToolExecutorDeps, MediaPreferencesSummary, } from "./memory/memory-tool.js";
5
- export { MemoryStore, MEMORY_ENTRY_DELIMITER, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_USER_CHAR_LIMIT, } from "./memory/memory-store.js";
6
- export type { MemoryStoreTarget, MemoryStoreResult, MemoryStoreOptions, MemoryStoreSerialized, } from "./memory/memory-store.js";
3
+ export { MEMORY_TOOL_NAME, MEMORY_TOOL_ACTIONS, MEMORY_TOOL_SCHEMA, MEMORY_TOOL_DESCRIPTION, MEMORY_TOOL_LABEL, isMemoryContentSafe, executeMemoryTool, } from "./memory/memory-tool.js";
4
+ export type { MemoryToolAction, MemoryToolParams, MemoryToolResult, MemoryToolExecutorDeps, } from "./memory/memory-tool.js";
5
+ export { Memdir, getMemdirPath, getIndexPath } from "./memory/memdir.js";
6
+ export type { MemdirFileInfo, MemdirResult } from "./memory/memdir.js";
7
7
  export { createQMemoryAdapter } from "./memory/qmemory-adapter.js";
8
- export type { QMemoryAdapterConfig, QMemoryHealthStatus, ExtractedMemoryItem } from "./memory/qmemory-adapter.js";
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";
@@ -0,0 +1,70 @@
1
+ export declare const RELEVANT_MEMORIES_CONFIG: {
2
+ /** Max topic files to consider during scan. */
3
+ readonly MAX_SCAN_FILES: 100;
4
+ /** Max files to surface per turn. */
5
+ readonly MAX_SELECTED: 5;
6
+ /** Max bytes per surfaced file (CC: 4096). */
7
+ readonly MAX_FILE_BYTES: 4096;
8
+ /** Max total bytes for all surfaced files combined. */
9
+ readonly MAX_TOTAL_BYTES: number;
10
+ /** Minimum score to be selected (0.0-1.0). */
11
+ readonly MIN_SCORE: 0.2;
12
+ /** Lines to read for header/description extraction. */
13
+ readonly HEADER_LINES: 10;
14
+ /** Recency boost: files modified within this many days get a bonus. */
15
+ readonly RECENCY_DAYS: 7;
16
+ /** Recency boost amount. */
17
+ readonly RECENCY_BOOST: 0.15;
18
+ };
19
+ /** Scanned memory file header (CC MemoryHeader parity). */
20
+ export interface MemoryFileHeader {
21
+ /** Filename (e.g. "lesson-docker.md") */
22
+ filename: string;
23
+ /** Absolute path */
24
+ filePath: string;
25
+ /** Last modified timestamp (ms since epoch) */
26
+ mtimeMs: number;
27
+ /** File size in bytes */
28
+ sizeBytes: number;
29
+ /** Description extracted from first non-heading line */
30
+ description: string | null;
31
+ /** Category inferred from filename prefix */
32
+ category: string | null;
33
+ }
34
+ /** A selected relevant memory with content loaded. */
35
+ export interface RelevantMemory {
36
+ /** Filename */
37
+ filename: string;
38
+ /** Full file path */
39
+ filePath: string;
40
+ /** Last modified timestamp */
41
+ mtimeMs: number;
42
+ /** Relevance score (0.0 - 1.0) */
43
+ score: number;
44
+ /** Content (possibly truncated) */
45
+ content: string;
46
+ /** Whether content was truncated */
47
+ truncated: boolean;
48
+ }
49
+ /**
50
+ * Find memory files relevant to a user query.
51
+ *
52
+ * CC parity: scans topic files, scores by keyword + filename + recency,
53
+ * selects top-N, loads content. No LLM needed (unlike CC's Sonnet call).
54
+ *
55
+ * @param query - User query text
56
+ * @param memoryDir - Root of the MEMDIR directory (~/.qlogicagent/memory/)
57
+ * @param alreadySurfaced - Paths already shown in prior turns (for dedup)
58
+ * @returns Relevant memories with content, sorted by score
59
+ */
60
+ export declare function findRelevantMemories(query: string, memoryDir: string, alreadySurfaced?: ReadonlySet<string>): Promise<RelevantMemory[]>;
61
+ /**
62
+ * Scan memory directory for topic files (excludes INDEX.md).
63
+ * Returns headers sorted by modification time (newest first).
64
+ */
65
+ export declare function scanMemoryHeaders(memoryDir: string): Promise<MemoryFileHeader[]>;
66
+ /**
67
+ * Format relevant memories as a single block for system prompt injection.
68
+ * CC parity: includes freshness header per file.
69
+ */
70
+ export declare function formatRelevantMemoriesBlock(memories: RelevantMemory[]): string;
@@ -0,0 +1,85 @@
1
+ /** Max chars for INDEX.md to inject into system prompt (CC uses 25KB, we use 12KB). */
2
+ export declare const INDEX_MAX_CHARS = 12288;
3
+ /** Max lines for INDEX.md injection. */
4
+ export declare const INDEX_MAX_LINES = 200;
5
+ /** Max chars for a single topic file. */
6
+ export declare const TOPIC_FILE_MAX_CHARS = 8192;
7
+ /** Root directory: ~/.qlogicagent/memory/ */
8
+ export declare function getMemdirPath(): string;
9
+ /** Full path to INDEX.md */
10
+ export declare function getIndexPath(): string;
11
+ export interface MemdirFileInfo {
12
+ name: string;
13
+ /** Size in bytes */
14
+ size: number;
15
+ /** Last modified ISO timestamp */
16
+ modifiedAt: string;
17
+ /** First non-empty line (preview) */
18
+ preview?: string;
19
+ }
20
+ export interface MemdirResult {
21
+ ok: boolean;
22
+ message: string;
23
+ /** File path relative to memdir */
24
+ file?: string;
25
+ /** Current INDEX.md char usage */
26
+ indexUsage?: string;
27
+ }
28
+ export declare function isMemoryContentSafe(text: string): boolean;
29
+ export declare class Memdir {
30
+ private readonly root;
31
+ private indexCache;
32
+ constructor(root?: string);
33
+ /** Get the root directory path of this MEMDIR. */
34
+ getRootPath(): string;
35
+ /** Ensure memdir exists with a default INDEX.md if missing. */
36
+ ensureInitialized(): void;
37
+ /**
38
+ * Get INDEX.md content for system prompt injection.
39
+ * Truncated to INDEX_MAX_CHARS / INDEX_MAX_LINES.
40
+ */
41
+ getIndexForPrompt(): string;
42
+ /** Get raw INDEX.md content (untruncated). */
43
+ getIndexRaw(): string;
44
+ /** Get INDEX.md usage stats. */
45
+ getIndexUsage(): {
46
+ chars: number;
47
+ lines: number;
48
+ percent: number;
49
+ };
50
+ /** Append a line/entry to INDEX.md. */
51
+ addToIndex(content: string): Promise<MemdirResult>;
52
+ /** Replace text in INDEX.md (str_replace semantics). */
53
+ replaceInIndex(oldText: string, newText: string): Promise<MemdirResult>;
54
+ /** Remove text from INDEX.md. */
55
+ removeFromIndex(oldText: string): Promise<MemdirResult>;
56
+ /** List all memory files (excluding INDEX.md). */
57
+ listFiles(): Promise<MemdirFileInfo[]>;
58
+ /** Create a new topic file. Fails if it already exists. */
59
+ createFile(name: string, content: string): Promise<MemdirResult>;
60
+ /** Write/overwrite a topic file. Auto-splits if content > 8KB. */
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;
67
+ /** Read a topic file. */
68
+ readFile(name: string): Promise<{
69
+ ok: boolean;
70
+ content?: string;
71
+ message: string;
72
+ }>;
73
+ /** Delete a topic file. INDEX.md cannot be deleted. */
74
+ deleteFile(name: string): Promise<MemdirResult>;
75
+ /** Search all memory files for keyword matches. Returns matching snippets. */
76
+ searchLocal(query: string): Promise<Array<{
77
+ file: string;
78
+ snippet: string;
79
+ score: number;
80
+ }>>;
81
+ private writeIndex;
82
+ private ensureDir;
83
+ /** Append an entry to the file listing section of INDEX.md (idempotent). */
84
+ private appendIndexEntry;
85
+ }
@@ -1,16 +1,8 @@
1
1
  import type { MemoryProvider, MemorySearchResult } from "qlogicagent-runtime-contracts";
2
- import type { MemoryStore, MemoryStoreTarget } from "./memory-store.js";
3
- export interface MediaPreferencesSummary {
4
- imageStyle?: string;
5
- videoStyle?: string;
6
- musicGenre?: string;
7
- musicMood?: string;
8
- primaryPurpose?: string;
9
- colorPreference?: string;
10
- }
2
+ import type { Memdir } from "./memdir.js";
11
3
  export declare const MEMORY_TOOL_NAME: "memory";
12
- export declare const MEMORY_TOOL_MAX_CONTENT_LENGTH = 2000;
13
- export declare const MEMORY_TOOL_ACTIONS: readonly ["add", "replace", "remove", "search"];
4
+ export declare const MEMORY_TOOL_LABEL = "Memory";
5
+ export declare const MEMORY_TOOL_ACTIONS: readonly ["add", "replace", "remove", "create_file", "write_file", "read_file", "delete_file", "list_files", "search"];
14
6
  export type MemoryToolAction = (typeof MEMORY_TOOL_ACTIONS)[number];
15
7
  export declare const MEMORY_TOOL_SCHEMA: {
16
8
  readonly type: "object";
@@ -20,68 +12,48 @@ export declare const MEMORY_TOOL_SCHEMA: {
20
12
  readonly enum: string[];
21
13
  readonly description: string;
22
14
  };
23
- readonly target: {
24
- readonly type: "string";
25
- readonly enum: readonly ["memory", "user"];
26
- readonly description: string;
27
- };
28
15
  readonly content: {
29
16
  readonly type: "string";
30
17
  readonly description: string;
31
18
  };
32
19
  readonly old_text: {
33
20
  readonly type: "string";
34
- readonly description: "Required for 'replace' and 'remove'. A substring that uniquely identifies the note entry to modify.";
21
+ readonly description: "For 'replace'/'remove': the exact text to find in INDEX.md.";
35
22
  };
36
- readonly query: {
23
+ readonly new_text: {
37
24
  readonly type: "string";
38
- readonly description: "Required for 'search'. Natural language query to find relevant memories.";
25
+ readonly description: "For 'replace': the replacement text.";
39
26
  };
40
- readonly category: {
27
+ readonly file: {
41
28
  readonly type: "string";
42
- readonly enum: readonly ["profile", "facts", "media", "projects"];
43
- readonly description: string;
29
+ readonly description: "Filename for file operations (e.g. 'project-notes.md', 'lesson-esbuild.md'). Must be kebab-case .md.";
30
+ };
31
+ readonly query: {
32
+ readonly type: "string";
33
+ readonly description: "For 'search': natural language query to find relevant memories.";
44
34
  };
45
35
  };
46
36
  readonly required: readonly ["action"];
47
37
  };
48
38
  export declare const MEMORY_TOOL_DESCRIPTION: string;
49
- export declare const MEMORY_TOOL_LABEL = "Memory";
50
39
  export declare function isMemoryContentSafe(text: string): boolean;
51
40
  export interface MemoryToolParams {
52
41
  action: MemoryToolAction;
53
- target?: MemoryStoreTarget;
54
42
  content?: string;
55
43
  old_text?: string;
44
+ new_text?: string;
45
+ file?: string;
56
46
  query?: string;
57
- category?: "profile" | "facts" | "media" | "projects";
58
47
  }
59
48
  export interface MemoryToolResult {
60
49
  ok: boolean;
61
50
  message: string;
62
51
  action: string;
63
- /** For MD store operations: live entry count */
64
- entryCount?: number;
65
- /** For MD store operations: usage string */
66
- usage?: string;
67
- /** For search: qmemory results */
68
52
  results?: MemorySearchResult[];
69
- /** Indicates MD store was mutated (consumer should persist) */
70
- storeModified?: boolean;
71
- errorCode?: string;
72
53
  }
73
54
  export interface MemoryToolExecutorDeps {
74
- /** QMemory provider for semantic search. */
75
- provider: MemoryProvider;
76
- /** Local MD memory store for notes. */
77
- store?: MemoryStore;
55
+ memdir: Memdir;
56
+ provider?: MemoryProvider;
78
57
  userId: string;
79
- sessionId?: string;
80
- /** Query recalled facts/memories by natural language. */
81
- queryGraph?: (query: string, userId: string) => string[];
82
- /** Retrieve user profile summary. */
83
- getProfileSummary?: (userId: string) => string | null;
84
- /** Retrieve media preferences. */
85
- getMediaPreferences?: (userId: string) => MediaPreferencesSummary | null;
86
58
  }
87
59
  export declare function executeMemoryTool(params: MemoryToolParams, deps: MemoryToolExecutorDeps): Promise<MemoryToolResult>;
@@ -19,6 +19,17 @@ export interface QMemoryAdapterConfig {
19
19
  /** Prefix prepended to userId for multi-tenant isolation. */
20
20
  userIdPrefix?: string;
21
21
  }
22
+ /** Options for triggering a decay cycle. */
23
+ export interface DecayOptions {
24
+ temporalExpiry?: boolean;
25
+ stalenessDecay?: boolean;
26
+ noiseArchival?: boolean;
27
+ }
28
+ /** Result of a decay cycle. */
29
+ export interface DecayResult {
30
+ decayed: number;
31
+ archived: number;
32
+ }
22
33
  /** Health status returned by qmemory `/v1/health/`. */
23
34
  export interface QMemoryHealthStatus {
24
35
  status: string;
@@ -40,4 +51,5 @@ export declare function createQMemoryAdapter(config: QMemoryAdapterConfig): Memo
40
51
  memoriesAdded: number;
41
52
  }>;
42
53
  feedback(memoryIds: string[], signal: string, sessionId?: string): Promise<void>;
54
+ triggerDecay(userId: string, options?: DecayOptions): Promise<DecayResult>;
43
55
  };
@@ -0,0 +1,54 @@
1
+ import type { QMemoryCategory } from "./categories.js";
2
+ /** Detected query scenario with preferred categories. */
3
+ export interface RecallCategoryHint {
4
+ /** Detected scenario label. */
5
+ scenario: QueryScenario;
6
+ /** Preferred categories for this scenario (ordered by priority). */
7
+ preferred: QMemoryCategory[];
8
+ /** Categories to deprioritize (still recalled but scored lower). */
9
+ deprioritized: QMemoryCategory[];
10
+ /** Confidence of scenario detection (0.0-1.0). */
11
+ confidence: number;
12
+ }
13
+ /** Known query scenarios. */
14
+ export type QueryScenario = "coding" | "config" | "conversation" | "learning" | "decision" | "general";
15
+ /**
16
+ * Detect the query scenario and return category preferences.
17
+ *
18
+ * Uses pattern matching on the user query to infer intent.
19
+ * Returns "general" (no filtering) when confidence is below threshold.
20
+ *
21
+ * @param query - User query text
22
+ * @returns Category hint with preferred/deprioritized categories
23
+ */
24
+ export declare function detectRecallCategories(query: string): RecallCategoryHint;
25
+ /**
26
+ * Apply category boost/penalty to a recall score.
27
+ *
28
+ * Used by recall hooks to adjust memory scores based on category alignment.
29
+ *
30
+ * @param baseScore - Original relevance score (0.0-1.0)
31
+ * @param memoryCategory - Category of the memory entry (if known)
32
+ * @param hint - Category hint from detectRecallCategories()
33
+ * @returns Adjusted score
34
+ */
35
+ export declare function applyCategoryBoost(baseScore: number, memoryCategory: string | undefined | null, hint: RecallCategoryHint): number;
36
+ /**
37
+ * Filter and re-rank a list of recalled memories based on category preferences.
38
+ *
39
+ * @param memories - Raw recalled memories with optional category
40
+ * @param hint - Category hint from detectRecallCategories()
41
+ * @param minScore - Minimum adjusted score to keep (default: 0)
42
+ * @returns Re-ranked memories (highest adjusted score first)
43
+ */
44
+ export declare function filterByCategory<T extends {
45
+ score?: number;
46
+ category?: string | null;
47
+ }>(memories: T[], hint: RecallCategoryHint, minScore?: number): T[];
48
+ /**
49
+ * Infer memory category from filename prefix convention.
50
+ * E.g. "lesson-docker.md" → "lesson", "fact-ports.md" → "fact"
51
+ *
52
+ * Exported for use by recall hooks.
53
+ */
54
+ export declare function inferCategoryFromFilename(filename: string): QMemoryCategory | null;
@@ -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.