qlogicagent 0.5.2 → 0.6.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 (167) hide show
  1. package/README.md +403 -402
  2. package/dist/agent.js +18 -0
  3. package/dist/cli.js +384 -0
  4. package/dist/contracts.js +1 -0
  5. package/dist/index.js +383 -0
  6. package/dist/orchestration.js +34 -0
  7. package/dist/types/agent/agent.d.ts +43 -0
  8. package/dist/types/agent/constants.d.ts +47 -0
  9. package/dist/types/agent/tool-access.d.ts +30 -0
  10. package/dist/types/agent/tool-loop.d.ts +94 -0
  11. package/dist/types/agent/types.d.ts +238 -0
  12. package/dist/types/cli/main.d.ts +11 -0
  13. package/dist/types/cli/stdio-server.d.ts +78 -0
  14. package/dist/types/cli/tool-bootstrap.d.ts +40 -0
  15. package/dist/types/cli/transport.d.ts +40 -0
  16. package/dist/types/config/config.d.ts +17 -0
  17. package/dist/types/contracts/hooks.d.ts +175 -0
  18. package/dist/types/contracts/index.d.ts +9 -0
  19. package/dist/types/contracts/planner.d.ts +35 -0
  20. package/dist/types/contracts/todo.d.ts +23 -0
  21. package/dist/types/index.d.ts +16 -0
  22. package/dist/types/llm/builtin-providers.d.ts +10 -0
  23. package/dist/types/llm/debug-transport.d.ts +12 -0
  24. package/dist/types/llm/index.d.ts +16 -0
  25. package/dist/types/llm/llm-client.d.ts +43 -0
  26. package/dist/types/llm/model-catalog.d.ts +53 -0
  27. package/dist/types/llm/provider-def.d.ts +59 -0
  28. package/dist/types/llm/provider-registry.d.ts +54 -0
  29. package/dist/types/llm/transport.d.ts +62 -0
  30. package/dist/types/llm/transports/anthropic-messages.d.ts +31 -0
  31. package/dist/types/llm/transports/openai-chat.d.ts +36 -0
  32. package/dist/types/orchestration/context/context-collapse.d.ts +58 -0
  33. package/dist/types/orchestration/context/context-compression.d.ts +301 -0
  34. package/dist/types/orchestration/context/reactive-compact.d.ts +73 -0
  35. package/dist/types/orchestration/context/turn-loop-guard.d.ts +86 -0
  36. package/dist/types/orchestration/error-handling/error-classification.d.ts +12 -0
  37. package/dist/types/orchestration/error-handling/failover-classification.d.ts +8 -0
  38. package/dist/types/orchestration/error-handling/failover-error.d.ts +33 -0
  39. package/dist/types/orchestration/error-handling/retry-loop.d.ts +69 -0
  40. package/dist/types/orchestration/index.d.ts +15 -0
  41. package/dist/types/orchestration/skill-improvement.d.ts +59 -0
  42. package/dist/types/orchestration/subagent/agent-registry.d.ts +46 -0
  43. package/dist/types/orchestration/subagent/fork-subagent.d.ts +98 -0
  44. package/dist/types/orchestration/subagent/task-types.d.ts +142 -0
  45. package/dist/types/orchestration/tool-loop/conversation-repair.d.ts +61 -0
  46. package/dist/types/orchestration/tool-loop/tool-choice-policy.d.ts +54 -0
  47. package/dist/types/orchestration/tool-loop/tool-loop-state.d.ts +50 -0
  48. package/dist/types/orchestration/tool-loop/tool-schema.d.ts +39 -0
  49. package/dist/types/runtime/execution/dream-agent.d.ts +199 -0
  50. package/dist/types/runtime/execution/forked-agent.d.ts +109 -0
  51. package/dist/types/runtime/execution/index.d.ts +6 -0
  52. package/dist/types/runtime/execution/progress-tracker.d.ts +78 -0
  53. package/dist/types/runtime/execution/remote-agent.d.ts +63 -0
  54. package/dist/types/runtime/execution/streaming-tool-executor.d.ts +100 -0
  55. package/dist/types/runtime/execution/tool-eligibility.d.ts +59 -0
  56. package/dist/types/runtime/execution/tool-result-storage.d.ts +87 -0
  57. package/dist/types/runtime/hooks/context-compression.d.ts +61 -0
  58. package/dist/types/runtime/hooks/hook-registry.d.ts +12 -0
  59. package/dist/types/runtime/hooks/index.d.ts +3 -0
  60. package/dist/types/runtime/hooks/memory-hooks.d.ts +49 -0
  61. package/dist/types/runtime/index.d.ts +5 -0
  62. package/dist/types/runtime/infra/agent-paths.d.ts +57 -0
  63. package/dist/types/runtime/infra/checkpoint-backend.d.ts +8 -0
  64. package/dist/types/runtime/infra/cleanup-registry.d.ts +23 -0
  65. package/dist/types/runtime/infra/disk-storage.d.ts +36 -0
  66. package/dist/types/runtime/infra/file-watcher.d.ts +72 -0
  67. package/dist/types/runtime/infra/index.d.ts +8 -0
  68. package/dist/types/runtime/infra/secure-storage.d.ts +81 -0
  69. package/dist/types/runtime/infra/task-runtime.d.ts +108 -0
  70. package/dist/types/runtime/infra/token-budget.d.ts +92 -0
  71. package/dist/types/runtime/infra/worktree-backend.d.ts +85 -0
  72. package/dist/types/runtime/prompt/environment-context.d.ts +23 -0
  73. package/dist/types/runtime/prompt/index.d.ts +3 -0
  74. package/dist/types/runtime/prompt/instruction-loader.d.ts +64 -0
  75. package/dist/types/runtime/prompt/system-prompt-sections.d.ts +63 -0
  76. package/dist/types/runtime/session/index.d.ts +2 -0
  77. package/dist/types/runtime/session/session-memory.d.ts +90 -0
  78. package/dist/types/runtime/session/session-persistence.d.ts +94 -0
  79. package/dist/types/runtime/session/session-state.d.ts +117 -0
  80. package/dist/types/skills/index.d.ts +119 -0
  81. package/dist/types/skills/mcp/index.d.ts +3 -0
  82. package/dist/types/skills/mcp/mcp-http-client.d.ts +66 -0
  83. package/dist/types/skills/mcp/mcp-manager.d.ts +83 -0
  84. package/dist/types/skills/mcp/mcp-stdio-client.d.ts +84 -0
  85. package/dist/types/skills/memory/memory-extractor.d.ts +64 -0
  86. package/dist/types/skills/memory/memory-store.d.ts +86 -0
  87. package/dist/types/skills/memory/memory-tool.d.ts +87 -0
  88. package/dist/types/skills/memory/qmemory-adapter.d.ts +42 -0
  89. package/dist/types/skills/permissions/bash-classifier.d.ts +30 -0
  90. package/dist/types/skills/permissions/classifier-cache.d.ts +51 -0
  91. package/dist/types/skills/permissions/denial-tracking.d.ts +42 -0
  92. package/dist/types/skills/permissions/hook-runner.d.ts +85 -0
  93. package/dist/types/skills/permissions/index.d.ts +12 -0
  94. package/dist/types/skills/permissions/permission-classifier.d.ts +41 -0
  95. package/dist/types/skills/permissions/rule-engine.d.ts +41 -0
  96. package/dist/types/skills/permissions/settings-watcher.d.ts +46 -0
  97. package/dist/types/skills/permissions/types.d.ts +113 -0
  98. package/dist/types/skills/plugins/index.d.ts +2 -0
  99. package/dist/types/skills/plugins/plugin-api.d.ts +38 -0
  100. package/dist/types/skills/plugins/plugin-loader.d.ts +42 -0
  101. package/dist/types/skills/plugins/plugin-marketplace.d.ts +61 -0
  102. package/dist/types/skills/portable-tool.d.ts +104 -0
  103. package/dist/types/skills/skill-system/skill-frontmatter.d.ts +19 -0
  104. package/dist/types/skills/skill-system/skill-guard.d.ts +23 -0
  105. package/dist/types/skills/skill-system/skill-loader.d.ts +16 -0
  106. package/dist/types/skills/skill-system/skill-source.d.ts +119 -0
  107. package/dist/types/skills/skill-system/skill-types.d.ts +199 -0
  108. package/dist/types/skills/think-tool.d.ts +16 -0
  109. package/dist/types/skills/todo-tool.d.ts +72 -0
  110. package/dist/types/skills/tools/agent-tool.d.ts +91 -0
  111. package/dist/types/skills/tools/apply-patch-tool.d.ts +29 -0
  112. package/dist/types/skills/tools/ask-user-tool.d.ts +80 -0
  113. package/dist/types/skills/tools/brief-tool.d.ts +74 -0
  114. package/dist/types/skills/tools/browser-tool.d.ts +114 -0
  115. package/dist/types/skills/tools/checkpoint-tool.d.ts +66 -0
  116. package/dist/types/skills/tools/config-tool.d.ts +63 -0
  117. package/dist/types/skills/tools/cron-tool.d.ts +116 -0
  118. package/dist/types/skills/tools/edit-tool.d.ts +43 -0
  119. package/dist/types/skills/tools/exec-tool.d.ts +97 -0
  120. package/dist/types/skills/tools/image-generate-tool.d.ts +62 -0
  121. package/dist/types/skills/tools/instructions-tool.d.ts +65 -0
  122. package/dist/types/skills/tools/lsp-tool.d.ts +153 -0
  123. package/dist/types/skills/tools/mcp-client-types.d.ts +269 -0
  124. package/dist/types/skills/tools/mcp-resource-tools.d.ts +14 -0
  125. package/dist/types/skills/tools/mcp-tool.d.ts +249 -0
  126. package/dist/types/skills/tools/monitor-tool.d.ts +113 -0
  127. package/dist/types/skills/tools/music-generate-tool.d.ts +55 -0
  128. package/dist/types/skills/tools/notebook-edit-tool.d.ts +15 -0
  129. package/dist/types/skills/tools/notify-tool.d.ts +53 -0
  130. package/dist/types/skills/tools/patch-tool.d.ts +45 -0
  131. package/dist/types/skills/tools/plan-mode-tool.d.ts +98 -0
  132. package/dist/types/skills/tools/read-tool.d.ts +51 -0
  133. package/dist/types/skills/tools/repl-tool.d.ts +70 -0
  134. package/dist/types/skills/tools/search-tool.d.ts +112 -0
  135. package/dist/types/skills/tools/send-message-tool.d.ts +51 -0
  136. package/dist/types/skills/tools/shell/bash-provider.d.ts +26 -0
  137. package/dist/types/skills/tools/shell/command-classification.d.ts +44 -0
  138. package/dist/types/skills/tools/shell/command-semantics.d.ts +14 -0
  139. package/dist/types/skills/tools/shell/destructive-command-warning.d.ts +10 -0
  140. package/dist/types/skills/tools/shell/exec-permissions.d.ts +52 -0
  141. package/dist/types/skills/tools/shell/index.d.ts +17 -0
  142. package/dist/types/skills/tools/shell/powershell-provider.d.ts +15 -0
  143. package/dist/types/skills/tools/shell/shell-command.d.ts +54 -0
  144. package/dist/types/skills/tools/shell/shell-exec.d.ts +33 -0
  145. package/dist/types/skills/tools/shell/shell-provider.d.ts +85 -0
  146. package/dist/types/skills/tools/shell/task-output.d.ts +45 -0
  147. package/dist/types/skills/tools/skill-invoke-tool.d.ts +46 -0
  148. package/dist/types/skills/tools/skill-list-tool.d.ts +33 -0
  149. package/dist/types/skills/tools/skill-manage-tool.d.ts +73 -0
  150. package/dist/types/skills/tools/skill-view-tool.d.ts +37 -0
  151. package/dist/types/skills/tools/sleep-tool.d.ts +49 -0
  152. package/dist/types/skills/tools/structured-output-tool.d.ts +116 -0
  153. package/dist/types/skills/tools/task-tool.d.ts +104 -0
  154. package/dist/types/skills/tools/team-tool.d.ts +89 -0
  155. package/dist/types/skills/tools/tool-search-tool.d.ts +51 -0
  156. package/dist/types/skills/tools/tts-tool.d.ts +38 -0
  157. package/dist/types/skills/tools/video-edit-tool.d.ts +69 -0
  158. package/dist/types/skills/tools/video-generate-tool.d.ts +62 -0
  159. package/dist/types/skills/tools/video-merge-tool.d.ts +105 -0
  160. package/dist/types/skills/tools/video-upscale-tool.d.ts +45 -0
  161. package/dist/types/skills/tools/web-fetch-tool.d.ts +78 -0
  162. package/dist/types/skills/tools/web-search-tool.d.ts +57 -0
  163. package/dist/types/skills/tools/workflow-tool.d.ts +44 -0
  164. package/dist/types/skills/tools/worktree-tool.d.ts +69 -0
  165. package/dist/types/skills/tools/write-tool.d.ts +45 -0
  166. package/dist/types/skills/tools.d.ts +65 -0
  167. package/package.json +4 -3
@@ -0,0 +1,86 @@
1
+ export declare const MEMORY_ENTRY_DELIMITER = "\n\u00A7\n";
2
+ export declare const DEFAULT_MEMORY_CHAR_LIMIT = 2200;
3
+ export declare const DEFAULT_USER_CHAR_LIMIT = 1375;
4
+ export type MemoryStoreTarget = "memory" | "user";
5
+ export interface MemoryStoreResult {
6
+ ok: boolean;
7
+ message: string;
8
+ target: MemoryStoreTarget;
9
+ entries: readonly string[];
10
+ entryCount: number;
11
+ usage: string;
12
+ errorCode?: string;
13
+ }
14
+ export interface MemoryStoreOptions {
15
+ memoryCharLimit?: number;
16
+ userCharLimit?: number;
17
+ /** When true, mutations automatically persist to ~/.qlogicagent/memory.json */
18
+ persistToDisk?: boolean;
19
+ }
20
+ export interface MemoryStoreSerialized {
21
+ memory: string;
22
+ user: string;
23
+ }
24
+ export declare class MemoryStore {
25
+ private memoryEntries;
26
+ private userEntries;
27
+ private frozenSnapshot;
28
+ private snapshotFrozen;
29
+ private saveTimer;
30
+ private readonly memoryCharLimit;
31
+ private readonly userCharLimit;
32
+ private readonly persistToDisk;
33
+ constructor(options?: MemoryStoreOptions);
34
+ /**
35
+ * Load from serialized form (e.g. from PG or filesystem).
36
+ * Deduplicates entries on load.
37
+ */
38
+ loadFromSerialized(data: Partial<MemoryStoreSerialized>): void;
39
+ /**
40
+ * Serialize current live state for persistence.
41
+ */
42
+ serialize(): MemoryStoreSerialized;
43
+ /**
44
+ * Load from disk (~/.qlogicagent/memory.json). No-op if file doesn't exist.
45
+ * Call this at startup when persistToDisk is enabled.
46
+ */
47
+ loadFromDisk(): Promise<void>;
48
+ /**
49
+ * Synchronous variant for use in sync constructors / init paths.
50
+ */
51
+ loadFromDiskSync(): void;
52
+ /**
53
+ * Schedule a debounced save to disk (500ms). Multiple rapid mutations
54
+ * coalesce into a single disk write.
55
+ */
56
+ private scheduleSave;
57
+ /** Flush any pending save immediately. Call before shutdown. */
58
+ flush(): Promise<void>;
59
+ /**
60
+ * Freeze current entries for system prompt injection.
61
+ * Call once at session start. After freezing, mutations update
62
+ * live state but NOT the system prompt block.
63
+ */
64
+ freezeSnapshot(): void;
65
+ /**
66
+ * Get frozen system prompt block for the given target.
67
+ * Returns empty string if no entries or not yet frozen.
68
+ */
69
+ getSystemPromptBlock(target: MemoryStoreTarget): string;
70
+ add(target: MemoryStoreTarget, content: string): MemoryStoreResult;
71
+ replace(target: MemoryStoreTarget, oldText: string, newContent: string): MemoryStoreResult;
72
+ remove(target: MemoryStoreTarget, oldText: string): MemoryStoreResult;
73
+ getEntries(target: MemoryStoreTarget): readonly string[];
74
+ getUsage(target: MemoryStoreTarget): {
75
+ used: number;
76
+ limit: number;
77
+ percent: number;
78
+ };
79
+ isEmpty(): boolean;
80
+ private entriesFor;
81
+ private charLimitFor;
82
+ private formatUsage;
83
+ private renderBlock;
84
+ private successResult;
85
+ private errorResult;
86
+ }
@@ -0,0 +1,87 @@
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
+ }
11
+ 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"];
14
+ export type MemoryToolAction = (typeof MEMORY_TOOL_ACTIONS)[number];
15
+ export declare const MEMORY_TOOL_SCHEMA: {
16
+ readonly type: "object";
17
+ readonly properties: {
18
+ readonly action: {
19
+ readonly type: "string";
20
+ readonly enum: string[];
21
+ readonly description: string;
22
+ };
23
+ readonly target: {
24
+ readonly type: "string";
25
+ readonly enum: readonly ["memory", "user"];
26
+ readonly description: string;
27
+ };
28
+ readonly content: {
29
+ readonly type: "string";
30
+ readonly description: string;
31
+ };
32
+ readonly old_text: {
33
+ readonly type: "string";
34
+ readonly description: "Required for 'replace' and 'remove'. A substring that uniquely identifies the note entry to modify.";
35
+ };
36
+ readonly query: {
37
+ readonly type: "string";
38
+ readonly description: "Required for 'search'. Natural language query to find relevant memories.";
39
+ };
40
+ readonly category: {
41
+ readonly type: "string";
42
+ readonly enum: readonly ["profile", "facts", "media", "projects"];
43
+ readonly description: string;
44
+ };
45
+ };
46
+ readonly required: readonly ["action"];
47
+ };
48
+ export declare const MEMORY_TOOL_DESCRIPTION: string;
49
+ export declare const MEMORY_TOOL_LABEL = "Memory";
50
+ export declare function isMemoryContentSafe(text: string): boolean;
51
+ export interface MemoryToolParams {
52
+ action: MemoryToolAction;
53
+ target?: MemoryStoreTarget;
54
+ content?: string;
55
+ old_text?: string;
56
+ query?: string;
57
+ category?: "profile" | "facts" | "media" | "projects";
58
+ }
59
+ export interface MemoryToolResult {
60
+ ok: boolean;
61
+ message: string;
62
+ 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
+ results?: MemorySearchResult[];
69
+ /** Indicates MD store was mutated (consumer should persist) */
70
+ storeModified?: boolean;
71
+ errorCode?: string;
72
+ }
73
+ export interface MemoryToolExecutorDeps {
74
+ /** QMemory provider for semantic search. */
75
+ provider: MemoryProvider;
76
+ /** Local MD memory store for notes. */
77
+ store?: MemoryStore;
78
+ 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
+ }
87
+ export declare function executeMemoryTool(params: MemoryToolParams, deps: MemoryToolExecutorDeps): Promise<MemoryToolResult>;
@@ -0,0 +1,42 @@
1
+ import type { MemoryIngestOptions, MemoryProvider } from "qlogicagent-runtime-contracts";
2
+ /** A pre-extracted memory item ready to be stored (no LLM needed). */
3
+ export interface ExtractedMemoryItem {
4
+ text: string;
5
+ category?: string;
6
+ importance?: number;
7
+ speaker?: string;
8
+ event_date?: string;
9
+ tags?: string[];
10
+ }
11
+ /** Configuration for the QMemory HTTP adapter. */
12
+ export interface QMemoryAdapterConfig {
13
+ /** Base URL of the qmemory server (e.g. "http://localhost:18800"). */
14
+ baseUrl: string;
15
+ /** Optional API key for authentication. */
16
+ apiKey?: string;
17
+ /** Request timeout in milliseconds (default: 5000). */
18
+ timeoutMs?: number;
19
+ /** Prefix prepended to userId for multi-tenant isolation. */
20
+ userIdPrefix?: string;
21
+ }
22
+ /** Health status returned by qmemory `/v1/health/`. */
23
+ export interface QMemoryHealthStatus {
24
+ status: string;
25
+ version: string;
26
+ memoryCount: number;
27
+ dbSizeBytes: number;
28
+ embeddingModel: string;
29
+ uptimeSeconds: number;
30
+ }
31
+ /**
32
+ * Create a MemoryProvider backed by a QMemory HTTP server.
33
+ *
34
+ * Uses `qlogicagent-adapter-claw` for HTTP transport.
35
+ */
36
+ export declare function createQMemoryAdapter(config: QMemoryAdapterConfig): MemoryProvider & {
37
+ health(): Promise<QMemoryHealthStatus>;
38
+ ingestExtracted(items: ExtractedMemoryItem[], userId: string, options?: MemoryIngestOptions): Promise<{
39
+ memoriesAdded: number;
40
+ }>;
41
+ feedback(memoryIds: string[], signal: string, sessionId?: string): Promise<void>;
42
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Bash Classifier — CC yoloClassifier bash branch parity.
3
+ *
4
+ * Specialized classifier for shell/bash commands.
5
+ * CC decomposes each bash tool call into structured analysis:
6
+ * 1. Parse the command string
7
+ * 2. Check against known safe/dangerous command patterns
8
+ * 3. Check working directory context
9
+ * 4. If ambiguous, defer to the LLM classifier
10
+ *
11
+ * This is a pre-filter that runs BEFORE the general classifier,
12
+ * so commonly-used safe shell commands bypass the LLM entirely.
13
+ *
14
+ * Reference: claude-code src/utils/permissions/yoloClassifier.ts (bash branch)
15
+ */
16
+ export interface BashClassifyResult {
17
+ decision: "allow" | "deny" | "defer";
18
+ reason: string;
19
+ /** Informational warning for destructive commands (CC parity). */
20
+ destructiveWarning?: string;
21
+ }
22
+ /**
23
+ * Classify a bash/shell command for safety.
24
+ *
25
+ * @param command - The shell command string
26
+ * @param cwd - Current working directory (for project context check)
27
+ * @param projectRoot - Project root directory
28
+ * @returns Classification result: allow / deny / defer (to LLM classifier)
29
+ */
30
+ export declare function classifyBashCommand(command: string, cwd?: string, projectRoot?: string): BashClassifyResult;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Classifier Cache — CC preToolUse approval cache parity.
3
+ *
4
+ * Caches already-judged tool use classification results to avoid
5
+ * redundant LLM classifier calls for identical tool invocations.
6
+ *
7
+ * CC pattern: The auto-mode classifier is expensive (2 LLM calls per tool).
8
+ * Caching results for identical (toolName + normalized args) combinations
9
+ * eliminates redundant classification within a session.
10
+ *
11
+ * Cache Key: `${toolName}::${normalizedArgs}`
12
+ * - Args are sorted-key JSON for deterministic comparison
13
+ * - Bash commands are normalized (whitespace collapse, env var strip)
14
+ *
15
+ * Cache is session-scoped (cleared on session end or mode change).
16
+ *
17
+ * Reference: claude-code src/utils/permissions/permissionCache.ts
18
+ */
19
+ export interface CachedClassification {
20
+ shouldBlock: boolean;
21
+ reason: string;
22
+ /** Timestamp when this classification was made */
23
+ classifiedAt: number;
24
+ /** How many times this cache entry was reused */
25
+ hitCount: number;
26
+ }
27
+ export declare class ClassifierCache {
28
+ private cache;
29
+ /**
30
+ * Look up a cached classification result.
31
+ * Returns undefined if not cached or expired.
32
+ */
33
+ get(toolName: string, args: Record<string, unknown>): CachedClassification | undefined;
34
+ /**
35
+ * Store a classification result.
36
+ */
37
+ set(toolName: string, args: Record<string, unknown>, result: {
38
+ shouldBlock: boolean;
39
+ reason: string;
40
+ }): void;
41
+ /**
42
+ * Check if a tool+args combination is cached.
43
+ */
44
+ has(toolName: string, args: Record<string, unknown>): boolean;
45
+ /** Clear all cached classifications (called on mode change or session end) */
46
+ clear(): void;
47
+ /** Number of cached entries */
48
+ get size(): number;
49
+ /** Total cache hits across all entries */
50
+ get totalHits(): number;
51
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Denial Tracking — CC denialTracking.ts parity.
3
+ *
4
+ * Tracks consecutive and total classifier denials to determine
5
+ * when to fall back to interactive prompting.
6
+ *
7
+ * CC reference: src/utils/permissions/denialTracking.ts
8
+ *
9
+ * Integration:
10
+ * - recordDenial() after each classifier block
11
+ * - recordSuccess() after each classifier allow
12
+ * - shouldFallbackToPrompting() before skipping approval dialog
13
+ */
14
+ export interface DenialTrackingState {
15
+ consecutiveDenials: number;
16
+ totalDenials: number;
17
+ }
18
+ export declare const DENIAL_LIMITS: {
19
+ /** Max consecutive denials before falling back to prompting. */
20
+ readonly maxConsecutive: 3;
21
+ /** Max total denials in a session before forcing prompt mode. */
22
+ readonly maxTotal: 20;
23
+ };
24
+ export declare function createDenialTrackingState(): DenialTrackingState;
25
+ /**
26
+ * Record a classifier denial. Increments both counters.
27
+ * Returns a new state object (immutable pattern).
28
+ */
29
+ export declare function recordDenial(state: DenialTrackingState): DenialTrackingState;
30
+ /**
31
+ * Record a classifier success. Resets consecutive counter only.
32
+ * Returns same reference if no change needed (optimization).
33
+ */
34
+ export declare function recordSuccess(state: DenialTrackingState): DenialTrackingState;
35
+ /**
36
+ * Check if the classifier should fall back to interactive prompting.
37
+ *
38
+ * CC pattern: After N consecutive denials or M total denials,
39
+ * the auto-classifier is likely miscalibrated — show the user
40
+ * the approval dialog instead.
41
+ */
42
+ export declare function shouldFallbackToPrompting(state: DenialTrackingState): boolean;
@@ -0,0 +1,85 @@
1
+ import type { HookRegistry } from "../../contracts/hooks.js";
2
+ import type { ToolDefinition } from "../../agent/types.js";
3
+ import { PermissionRuleEngine } from "./rule-engine.js";
4
+ import type { PermissionUpdate, ApprovalRequest, ApprovalResponse } from "./types.js";
5
+ import { type ClassifierLLMCall } from "./permission-classifier.js";
6
+ import type { PermissionRole } from "../../orchestration/subagent/task-types.js";
7
+ export interface PermissionCheckerDeps {
8
+ ruleEngine: PermissionRuleEngine;
9
+ hookRegistry: HookRegistry;
10
+ /**
11
+ * Callback to send an approval request to the host (Gateway/Electron).
12
+ * Must return a promise that resolves when the user responds.
13
+ * If the host does not support approval, this should reject or return denied.
14
+ */
15
+ onRequestApproval: (request: ApprovalRequest) => Promise<ApprovalResponse>;
16
+ /** Called when a persistent permission update is returned from the approval dialog */
17
+ onPermissionUpdate?: (update: PermissionUpdate) => void;
18
+ /** Called when a tool is denied (for logging/observability) */
19
+ onDenied?: (toolName: string, message: string) => void;
20
+ /**
21
+ * LLM call function for the auto-mode classifier (cc yoloClassifier pattern).
22
+ * If not provided, auto mode falls back to the approval dialog.
23
+ */
24
+ classifierLLMCall?: ClassifierLLMCall;
25
+ /**
26
+ * Recent conversation messages for classifier context.
27
+ * Called lazily when the classifier needs to run.
28
+ */
29
+ getRecentMessages?: () => import("../../agent/types.js").ChatMessage[];
30
+ /**
31
+ * Permission role context (CC: interactive/coordinator/worker).
32
+ * Determines how the checker behaves:
33
+ * - interactive: full approval dialog flow (default)
34
+ * - coordinator: auto-approve non-destructive ops, no user prompts
35
+ * - worker: classifier-only path, no approval dialog fallback
36
+ */
37
+ permissionRole?: PermissionRole;
38
+ }
39
+ export declare class PermissionChecker {
40
+ private readonly ruleEngine;
41
+ private readonly hookRegistry;
42
+ private readonly onRequestApproval;
43
+ private readonly onPermissionUpdate;
44
+ private readonly onDenied;
45
+ private readonly classifierLLMCall;
46
+ private readonly getRecentMessages;
47
+ private readonly permissionRole;
48
+ private readonly pendingApprovals;
49
+ private unregisterHook;
50
+ /** Tool meta cache — populated from ToolDefinition[] at agent creation */
51
+ private toolMetaCache;
52
+ /** Classifier result cache — avoids redundant LLM calls (CC permissionCache parity) */
53
+ private classifierCache;
54
+ /** Denial tracking state — CC denialTracking.ts parity */
55
+ private denialTracking;
56
+ constructor(deps: PermissionCheckerDeps);
57
+ /**
58
+ * Register the permission check hook on the HookRegistry.
59
+ * Returns an unregister function.
60
+ */
61
+ register(): () => void;
62
+ /**
63
+ * Resolve an incoming approval response (called by host RPC handler).
64
+ */
65
+ resolveApproval(response: ApprovalResponse): void;
66
+ /**
67
+ * Update tool metadata cache (call when tool list changes).
68
+ */
69
+ setToolMeta(tools: ToolDefinition[]): void;
70
+ get ruleEngineRef(): PermissionRuleEngine;
71
+ /** Fire permission.denied hook + onDenied callback */
72
+ private fireDenied;
73
+ private handleResult;
74
+ /**
75
+ * Worker/coordinator "ask" handler: classifier-only, no approval dialog.
76
+ * CC pattern: headless workers never prompt users.
77
+ */
78
+ private handleWorkerAsk;
79
+ private requestApproval;
80
+ /**
81
+ * Clear the classifier cache (CC parity: called on mode change / session end).
82
+ */
83
+ clearClassifierCache(): void;
84
+ private cancelAllPending;
85
+ }
@@ -0,0 +1,12 @@
1
+ export { PermissionRuleEngine, parsePermissionConfig } from "./rule-engine.js";
2
+ export { PermissionChecker } from "./hook-runner.js";
3
+ export type { PermissionCheckerDeps } from "./hook-runner.js";
4
+ export { classifyToolAction, isAutoModeAllowlistedTool, } from "./permission-classifier.js";
5
+ export type { ClassifierLLMCall, ClassifierResult, } from "./permission-classifier.js";
6
+ export { classifyBashCommand } from "./bash-classifier.js";
7
+ export type { BashClassifyResult } from "./bash-classifier.js";
8
+ export { ClassifierCache } from "./classifier-cache.js";
9
+ export type { CachedClassification } from "./classifier-cache.js";
10
+ export { watchSettings, loadInitialSettings } from "./settings-watcher.js";
11
+ export type { SettingsFile, SettingsWatcherDeps } from "./settings-watcher.js";
12
+ export type { PermissionMode, PermissionBehavior, PermissionResult, PermissionRuleEntry, PermissionConfig, PermissionUpdate, PermissionDecisionReason, ToolPermissionCheckInput, ApprovalRequest, ApprovalResponse, } from "./types.js";
@@ -0,0 +1,41 @@
1
+ import type { ChatMessage } from "../../agent/types.js";
2
+ export interface ClassifierResult {
3
+ shouldBlock: boolean;
4
+ reason: string;
5
+ stage: "allowlist" | "fast" | "thinking";
6
+ durationMs: number;
7
+ }
8
+ /**
9
+ * LLM call interface — injected by the host so the classifier
10
+ * doesn't depend on a specific LLM client.
11
+ */
12
+ export interface ClassifierLLMCall {
13
+ (params: {
14
+ system: string;
15
+ messages: Array<{
16
+ role: "user" | "assistant";
17
+ content: string;
18
+ }>;
19
+ maxTokens: number;
20
+ temperature: number;
21
+ stop?: string[];
22
+ /** If true, host should cache the system prompt (cc cache_control). */
23
+ cacheSystemPrompt?: boolean;
24
+ }): Promise<{
25
+ text: string;
26
+ usage?: {
27
+ promptTokens: number;
28
+ completionTokens: number;
29
+ };
30
+ }>;
31
+ }
32
+ export declare function isAutoModeAllowlistedTool(toolName: string): boolean;
33
+ /**
34
+ * Two-stage XML classifier for auto-mode permission decisions.
35
+ *
36
+ * Stage 1 (fast): Quick classification with minimal tokens.
37
+ * Stage 2 (thinking): Only if stage 1 blocks, do a more careful review.
38
+ *
39
+ * cc reference: classifyYoloAction() in yoloClassifier.ts
40
+ */
41
+ export declare function classifyToolAction(toolName: string, toolArgs: Record<string, unknown>, recentMessages: ChatMessage[], llmCall: ClassifierLLMCall): Promise<ClassifierResult>;
@@ -0,0 +1,41 @@
1
+ import type { PermissionMode, PermissionBehavior, PermissionResult, PermissionRuleEntry, PermissionConfig, PermissionUpdate, ToolPermissionCheckInput } from "./types.js";
2
+ export declare class PermissionRuleEngine {
3
+ private mode;
4
+ private rules;
5
+ private defaultBehavior;
6
+ private compiledPatterns;
7
+ constructor(config: PermissionConfig);
8
+ getMode(): PermissionMode;
9
+ setMode(mode: PermissionMode): void;
10
+ getRules(): readonly PermissionRuleEntry[];
11
+ getDefaultBehavior(): PermissionBehavior;
12
+ /** Replace all rules at once (for settings hot-reload). */
13
+ replaceRules(rules: PermissionRuleEntry[]): void;
14
+ /** Update the default behavior (for settings hot-reload). */
15
+ setDefaultBehavior(behavior: PermissionBehavior): void;
16
+ addRule(rule: PermissionRuleEntry): void;
17
+ /**
18
+ * Apply a persistent permission update (e.g. from approval dialog "always allow").
19
+ */
20
+ applyUpdate(update: PermissionUpdate): void;
21
+ /**
22
+ * 4-layer permission check (cc hasPermissionsToUseTool parity).
23
+ *
24
+ * Layer 0: Mode override
25
+ * Layer 1: Explicit rules (first match wins)
26
+ * Layer 2: Tool metadata (isReadOnly/isDangerous/requiresApproval)
27
+ * Layer 3: Default behavior
28
+ */
29
+ check(input: ToolPermissionCheckInput): PermissionResult;
30
+ private compileRules;
31
+ }
32
+ /**
33
+ * Parse permission config from Gateway-injected or local settings.
34
+ *
35
+ * Accepts cc-compatible format:
36
+ * { mode?: "default", allow: [...], deny: [...], ask: [...], default?: "allow" }
37
+ *
38
+ * And extended rule format:
39
+ * { rules: [{ pattern, behavior, reason, source }] }
40
+ */
41
+ export declare function parsePermissionConfig(raw: unknown): PermissionConfig;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Settings Watcher — CC settings.json hot-reload parity.
3
+ *
4
+ * Watches the project-local settings file and reloads permission rules
5
+ * when it changes on disk. This allows users to adjust permission rules
6
+ * without restarting the agent session.
7
+ *
8
+ * Settings file location: `.qlogicagent/settings.json` in the project root
9
+ *
10
+ * Watched fields:
11
+ * - permissionMode: PermissionMode
12
+ * - permissionRules: PermissionRuleEntry[]
13
+ * - defaultBehavior: PermissionBehavior
14
+ *
15
+ * CC reference: src/utils/settings/settings.ts (watchSettings, applySettings)
16
+ */
17
+ import type { HookRegistry } from "../../contracts/hooks.js";
18
+ import type { PermissionRuleEntry, PermissionMode, PermissionBehavior } from "./types.js";
19
+ import { PermissionRuleEngine } from "./rule-engine.js";
20
+ /** On-disk settings file schema */
21
+ export interface SettingsFile {
22
+ permissionMode?: PermissionMode;
23
+ permissionRules?: PermissionRuleEntry[];
24
+ defaultBehavior?: PermissionBehavior;
25
+ }
26
+ export interface SettingsWatcherDeps {
27
+ /** Project root directory (where .qlogicagent/ lives) */
28
+ projectRoot: string;
29
+ /** Permission rule engine to update on changes */
30
+ ruleEngine: PermissionRuleEngine;
31
+ /** Hook registry for config.changed events */
32
+ hooks?: HookRegistry;
33
+ /** Logger */
34
+ log?: (msg: string) => void;
35
+ }
36
+ /**
37
+ * Watch the settings file for changes and hot-reload permission rules.
38
+ *
39
+ * Returns an unsubscribe function.
40
+ */
41
+ export declare function watchSettings(deps: SettingsWatcherDeps): () => void;
42
+ /**
43
+ * Load initial settings (non-watching).
44
+ * Call at session start to apply project settings before the watcher starts.
45
+ */
46
+ export declare function loadInitialSettings(projectRoot: string, ruleEngine: PermissionRuleEngine): Promise<SettingsFile | null>;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * User-configurable permission modes.
3
+ *
4
+ * cc reference:
5
+ * 'default' → normal prompting
6
+ * 'bypassPermissions' → auto-accept all
7
+ * 'acceptEdits' → auto-accept edits only
8
+ * 'dontAsk' → auto-deny all
9
+ * 'plan' → planning mode (pause execution)
10
+ *
11
+ * We keep the cc names for compatibility.
12
+ */
13
+ export type PermissionMode = "default" | "bypassPermissions" | "acceptEdits" | "dontAsk" | "plan" | "auto";
14
+ export declare const PERMISSION_MODES: readonly PermissionMode[];
15
+ export type PermissionBehavior = "allow" | "deny" | "ask";
16
+ export type PermissionDecisionReason = {
17
+ type: "rule";
18
+ rule: PermissionRuleEntry;
19
+ } | {
20
+ type: "mode";
21
+ mode: PermissionMode;
22
+ } | {
23
+ type: "hook";
24
+ hookName: string;
25
+ reason: string;
26
+ } | {
27
+ type: "classifier";
28
+ classifier: string;
29
+ reason: string;
30
+ } | {
31
+ type: "tool_check";
32
+ reason: string;
33
+ } | {
34
+ type: "eligibility";
35
+ reasonCodes: string[];
36
+ } | {
37
+ type: "sandbox";
38
+ reason: string;
39
+ } | {
40
+ type: "other";
41
+ reason: string;
42
+ };
43
+ export interface PermissionAllowResult {
44
+ behavior: "allow";
45
+ updatedInput?: Record<string, unknown>;
46
+ decisionReason?: PermissionDecisionReason;
47
+ }
48
+ export interface PermissionAskResult {
49
+ behavior: "ask";
50
+ message: string;
51
+ toolName: string;
52
+ input?: Record<string, unknown>;
53
+ suggestions?: PermissionUpdate[];
54
+ decisionReason?: PermissionDecisionReason;
55
+ }
56
+ export interface PermissionDenyResult {
57
+ behavior: "deny";
58
+ message: string;
59
+ decisionReason: PermissionDecisionReason;
60
+ }
61
+ export type PermissionResult = PermissionAllowResult | PermissionAskResult | PermissionDenyResult;
62
+ export interface PermissionUpdate {
63
+ /** Tool name or glob pattern */
64
+ pattern: string;
65
+ /** New rule to apply */
66
+ behavior: PermissionBehavior;
67
+ /** Human-readable description */
68
+ description?: string;
69
+ }
70
+ export interface PermissionRuleEntry {
71
+ /** Exact tool name or glob pattern */
72
+ pattern: string;
73
+ /** Action for matching tools */
74
+ behavior: PermissionBehavior;
75
+ /** Optional reason for logging/display */
76
+ reason?: string;
77
+ /** Source of this rule (config/user/plugin) */
78
+ source?: string;
79
+ }
80
+ export interface PermissionConfig {
81
+ /** Active permission mode */
82
+ mode: PermissionMode;
83
+ /** Rules evaluated in order; first match wins */
84
+ rules: PermissionRuleEntry[];
85
+ /** Default behavior when no rule matches */
86
+ defaultBehavior: PermissionBehavior;
87
+ }
88
+ export interface ToolPermissionCheckInput {
89
+ toolName: string;
90
+ arguments?: Record<string, unknown>;
91
+ /** Tool metadata from ToolDefinition.meta */
92
+ meta?: {
93
+ isReadOnly?: boolean;
94
+ isDangerous?: boolean;
95
+ requiresApproval?: boolean;
96
+ parallelSafe?: boolean;
97
+ };
98
+ }
99
+ export interface ApprovalRequest {
100
+ approvalId: string;
101
+ callId: string;
102
+ toolName: string;
103
+ arguments?: Record<string, unknown>;
104
+ message: string;
105
+ suggestions?: PermissionUpdate[];
106
+ }
107
+ export interface ApprovalResponse {
108
+ approvalId: string;
109
+ decision: "approved" | "denied";
110
+ updatedInput?: Record<string, unknown>;
111
+ /** Persistent rule to save */
112
+ permissionUpdate?: PermissionUpdate;
113
+ }