@phuetz/code-buddy 0.1.24 → 0.1.26
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.
- package/README.md +1049 -741
- package/dist/agent/codebuddy-agent.d.ts +5 -0
- package/dist/agent/codebuddy-agent.js +46 -1
- package/dist/agent/codebuddy-agent.js.map +1 -1
- package/dist/agent/execution/agent-executor.d.ts +12 -0
- package/dist/agent/execution/agent-executor.js +147 -6
- package/dist/agent/execution/agent-executor.js.map +1 -1
- package/dist/agent/lessons-tracker.d.ts +50 -0
- package/dist/agent/lessons-tracker.js +234 -0
- package/dist/agent/lessons-tracker.js.map +1 -0
- package/dist/agent/message-queue.d.ts +39 -2
- package/dist/agent/message-queue.js +67 -2
- package/dist/agent/message-queue.js.map +1 -1
- package/dist/agent/middleware/index.d.ts +1 -0
- package/dist/agent/middleware/index.js +1 -0
- package/dist/agent/middleware/index.js.map +1 -1
- package/dist/agent/middleware/workflow-guard.d.ts +21 -0
- package/dist/agent/middleware/workflow-guard.js +94 -0
- package/dist/agent/middleware/workflow-guard.js.map +1 -0
- package/dist/agent/repo-profiler.d.ts +61 -0
- package/dist/agent/repo-profiler.js +295 -0
- package/dist/agent/repo-profiler.js.map +1 -0
- package/dist/agent/response-constraint.d.ts +61 -0
- package/dist/agent/response-constraint.js +91 -0
- package/dist/agent/response-constraint.js.map +1 -0
- package/dist/agent/todo-tracker.d.ts +67 -0
- package/dist/agent/todo-tracker.js +245 -0
- package/dist/agent/todo-tracker.js.map +1 -0
- package/dist/agent/tool-handler.d.ts +11 -0
- package/dist/agent/tool-handler.js +79 -1
- package/dist/agent/tool-handler.js.map +1 -1
- package/dist/agent/types.d.ts +20 -2
- package/dist/agent/wide-research.d.ts +93 -0
- package/dist/agent/wide-research.js +232 -0
- package/dist/agent/wide-research.js.map +1 -0
- package/dist/channels/index.d.ts +2 -0
- package/dist/channels/index.js +2 -0
- package/dist/channels/index.js.map +1 -1
- package/dist/channels/pro/callback-router.d.ts +54 -0
- package/dist/channels/pro/callback-router.js +178 -0
- package/dist/channels/pro/callback-router.js.map +1 -0
- package/dist/channels/pro/ci-watcher.d.ts +86 -0
- package/dist/channels/pro/ci-watcher.js +343 -0
- package/dist/channels/pro/ci-watcher.js.map +1 -0
- package/dist/channels/pro/diff-first.d.ts +63 -0
- package/dist/channels/pro/diff-first.js +187 -0
- package/dist/channels/pro/diff-first.js.map +1 -0
- package/dist/channels/pro/enhanced-commands.d.ts +83 -0
- package/dist/channels/pro/enhanced-commands.js +218 -0
- package/dist/channels/pro/enhanced-commands.js.map +1 -0
- package/dist/channels/pro/index.d.ts +19 -0
- package/dist/channels/pro/index.js +21 -0
- package/dist/channels/pro/index.js.map +1 -0
- package/dist/channels/pro/pro-features.d.ts +79 -0
- package/dist/channels/pro/pro-features.js +203 -0
- package/dist/channels/pro/pro-features.js.map +1 -0
- package/dist/channels/pro/run-commands.d.ts +59 -0
- package/dist/channels/pro/run-commands.js +122 -0
- package/dist/channels/pro/run-commands.js.map +1 -0
- package/dist/channels/pro/run-tracker.d.ts +74 -0
- package/dist/channels/pro/run-tracker.js +252 -0
- package/dist/channels/pro/run-tracker.js.map +1 -0
- package/dist/channels/pro/scoped-auth.d.ts +97 -0
- package/dist/channels/pro/scoped-auth.js +340 -0
- package/dist/channels/pro/scoped-auth.js.map +1 -0
- package/dist/channels/pro/text-formatter.d.ts +27 -0
- package/dist/channels/pro/text-formatter.js +269 -0
- package/dist/channels/pro/text-formatter.js.map +1 -0
- package/dist/channels/pro/types.d.ts +242 -0
- package/dist/channels/pro/types.js +14 -0
- package/dist/channels/pro/types.js.map +1 -0
- package/dist/channels/streaming-policy.d.ts +66 -0
- package/dist/channels/streaming-policy.js +266 -0
- package/dist/channels/streaming-policy.js.map +1 -0
- package/dist/channels/telegram/ci-watcher.d.ts +5 -0
- package/dist/channels/telegram/ci-watcher.js +5 -0
- package/dist/channels/telegram/ci-watcher.js.map +1 -0
- package/dist/channels/telegram/client.d.ts +28 -0
- package/dist/channels/telegram/client.js +147 -1
- package/dist/channels/telegram/client.js.map +1 -1
- package/dist/channels/telegram/diff-first.d.ts +5 -0
- package/dist/channels/telegram/diff-first.js +5 -0
- package/dist/channels/telegram/diff-first.js.map +1 -0
- package/dist/channels/telegram/enhanced-commands.d.ts +6 -0
- package/dist/channels/telegram/enhanced-commands.js +6 -0
- package/dist/channels/telegram/enhanced-commands.js.map +1 -0
- package/dist/channels/telegram/index.d.ts +6 -0
- package/dist/channels/telegram/index.js +6 -0
- package/dist/channels/telegram/index.js.map +1 -1
- package/dist/channels/telegram/pro-formatter.d.ts +30 -0
- package/dist/channels/telegram/pro-formatter.js +276 -0
- package/dist/channels/telegram/pro-formatter.js.map +1 -0
- package/dist/channels/telegram/run-commands.d.ts +5 -0
- package/dist/channels/telegram/run-commands.js +6 -0
- package/dist/channels/telegram/run-commands.js.map +1 -0
- package/dist/channels/telegram/run-tracker.d.ts +5 -0
- package/dist/channels/telegram/run-tracker.js +5 -0
- package/dist/channels/telegram/run-tracker.js.map +1 -0
- package/dist/channels/telegram/scoped-auth.d.ts +6 -0
- package/dist/channels/telegram/scoped-auth.js +5 -0
- package/dist/channels/telegram/scoped-auth.js.map +1 -0
- package/dist/channels/telegram/types.d.ts +34 -0
- package/dist/codebuddy/client.js +14 -1
- package/dist/codebuddy/client.js.map +1 -1
- package/dist/commands/dev/index.d.ts +12 -0
- package/dist/commands/dev/index.js +231 -0
- package/dist/commands/dev/index.js.map +1 -0
- package/dist/commands/dev/workflows.d.ts +31 -0
- package/dist/commands/dev/workflows.js +214 -0
- package/dist/commands/dev/workflows.js.map +1 -0
- package/dist/commands/execpolicy.d.ts +17 -0
- package/dist/commands/execpolicy.js +155 -0
- package/dist/commands/execpolicy.js.map +1 -0
- package/dist/commands/knowledge.d.ts +13 -0
- package/dist/commands/knowledge.js +142 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/lessons.d.ts +11 -0
- package/dist/commands/lessons.js +129 -0
- package/dist/commands/lessons.js.map +1 -0
- package/dist/commands/pairing.d.ts +14 -0
- package/dist/commands/pairing.js +132 -0
- package/dist/commands/pairing.js.map +1 -0
- package/dist/commands/research/index.d.ts +13 -0
- package/dist/commands/research/index.js +91 -0
- package/dist/commands/research/index.js.map +1 -0
- package/dist/commands/run-cli/index.d.ts +11 -0
- package/dist/commands/run-cli/index.js +49 -0
- package/dist/commands/run-cli/index.js.map +1 -0
- package/dist/commands/todos.d.ts +9 -0
- package/dist/commands/todos.js +119 -0
- package/dist/commands/todos.js.map +1 -0
- package/dist/config/toml-config.d.ts +21 -0
- package/dist/config/toml-config.js +15 -0
- package/dist/config/toml-config.js.map +1 -1
- package/dist/context/enhanced-compression.js +12 -1
- package/dist/context/enhanced-compression.js.map +1 -1
- package/dist/context/observation-variator.d.ts +44 -0
- package/dist/context/observation-variator.js +83 -0
- package/dist/context/observation-variator.js.map +1 -0
- package/dist/context/precompaction-flush.d.ts +40 -0
- package/dist/context/precompaction-flush.js +134 -0
- package/dist/context/precompaction-flush.js.map +1 -0
- package/dist/context/restorable-compression.d.ts +80 -0
- package/dist/context/restorable-compression.js +228 -0
- package/dist/context/restorable-compression.js.map +1 -0
- package/dist/daemon/daily-reset.d.ts +77 -0
- package/dist/daemon/daily-reset.js +175 -0
- package/dist/daemon/daily-reset.js.map +1 -0
- package/dist/daemon/index.d.ts +1 -0
- package/dist/daemon/index.js +1 -0
- package/dist/daemon/index.js.map +1 -1
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge/knowledge-manager.d.ts +77 -0
- package/dist/knowledge/knowledge-manager.js +244 -0
- package/dist/knowledge/knowledge-manager.js.map +1 -0
- package/dist/observability/run-store.d.ts +133 -0
- package/dist/observability/run-store.js +419 -0
- package/dist/observability/run-store.js.map +1 -0
- package/dist/observability/run-viewer.d.ts +33 -0
- package/dist/observability/run-viewer.js +254 -0
- package/dist/observability/run-viewer.js.map +1 -0
- package/dist/optimization/cache-breakpoints.d.ts +52 -0
- package/dist/optimization/cache-breakpoints.js +97 -0
- package/dist/optimization/cache-breakpoints.js.map +1 -0
- package/dist/persistence/session-store.d.ts +3 -1
- package/dist/persistence/session-store.js +1 -1
- package/dist/persistence/session-store.js.map +1 -1
- package/dist/prompts/system-base.js +51 -7
- package/dist/prompts/system-base.js.map +1 -1
- package/dist/prompts/variation-injector.d.ts +55 -0
- package/dist/prompts/variation-injector.js +171 -0
- package/dist/prompts/variation-injector.js.map +1 -0
- package/dist/prompts/workflow-rules.d.ts +10 -0
- package/dist/prompts/workflow-rules.js +79 -0
- package/dist/prompts/workflow-rules.js.map +1 -0
- package/dist/sandbox/execpolicy.d.ts +45 -0
- package/dist/sandbox/execpolicy.js +80 -0
- package/dist/sandbox/execpolicy.js.map +1 -1
- package/dist/sandbox/os-sandbox.d.ts +25 -0
- package/dist/sandbox/os-sandbox.js +73 -0
- package/dist/sandbox/os-sandbox.js.map +1 -1
- package/dist/security/security-audit.d.ts +10 -0
- package/dist/security/security-audit.js +116 -0
- package/dist/security/security-audit.js.map +1 -1
- package/dist/security/shell-env-policy.d.ts +45 -0
- package/dist/security/shell-env-policy.js +141 -0
- package/dist/security/shell-env-policy.js.map +1 -0
- package/dist/security/ssrf-guard.d.ts +61 -0
- package/dist/security/ssrf-guard.js +382 -0
- package/dist/security/ssrf-guard.js.map +1 -0
- package/dist/security/write-policy.d.ts +57 -0
- package/dist/security/write-policy.js +117 -0
- package/dist/security/write-policy.js.map +1 -0
- package/dist/services/prompt-builder.js +37 -0
- package/dist/services/prompt-builder.js.map +1 -1
- package/dist/themes/theme-schema.d.ts +10 -10
- package/dist/tools/ask-human-tool.d.ts +62 -0
- package/dist/tools/ask-human-tool.js +112 -0
- package/dist/tools/ask-human-tool.js.map +1 -0
- package/dist/tools/bash/bash-tool.d.ts +15 -0
- package/dist/tools/bash/bash-tool.js +62 -0
- package/dist/tools/bash/bash-tool.js.map +1 -1
- package/dist/tools/bash/command-validator.d.ts +1 -0
- package/dist/tools/bash/command-validator.js +5 -0
- package/dist/tools/bash/command-validator.js.map +1 -1
- package/dist/tools/create-skill-tool.d.ts +87 -0
- package/dist/tools/create-skill-tool.js +142 -0
- package/dist/tools/create-skill-tool.js.map +1 -0
- package/dist/tools/fetch-tool.js +5 -3
- package/dist/tools/fetch-tool.js.map +1 -1
- package/dist/tools/hooks/default-hooks.js +24 -23
- package/dist/tools/hooks/default-hooks.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-tool.d.ts +22 -0
- package/dist/tools/plan-tool.js +128 -0
- package/dist/tools/plan-tool.js.map +1 -0
- package/dist/tools/registry/attention-tools.d.ts +32 -0
- package/dist/tools/registry/attention-tools.js +225 -0
- package/dist/tools/registry/attention-tools.js.map +1 -0
- package/dist/tools/registry/index.d.ts +9 -1
- package/dist/tools/registry/index.js +30 -2
- package/dist/tools/registry/index.js.map +1 -1
- package/dist/tools/registry/knowledge-tools.d.ts +46 -0
- package/dist/tools/registry/knowledge-tools.js +293 -0
- package/dist/tools/registry/knowledge-tools.js.map +1 -0
- package/dist/tools/registry/lessons-tools.d.ts +48 -0
- package/dist/tools/registry/lessons-tools.js +359 -0
- package/dist/tools/registry/lessons-tools.js.map +1 -0
- package/dist/tools/registry/plan-tools.d.ts +2 -0
- package/dist/tools/registry/plan-tools.js +7 -0
- package/dist/tools/registry/plan-tools.js.map +1 -0
- package/dist/tools/registry/script-tools.d.ts +2 -0
- package/dist/tools/registry/script-tools.js +7 -0
- package/dist/tools/registry/script-tools.js.map +1 -0
- package/dist/tools/registry/tool-aliases.d.ts +44 -0
- package/dist/tools/registry/tool-aliases.js +130 -0
- package/dist/tools/registry/tool-aliases.js.map +1 -0
- package/dist/tools/run-script-tool.d.ts +13 -0
- package/dist/tools/run-script-tool.js +146 -0
- package/dist/tools/run-script-tool.js.map +1 -0
- package/dist/tools/web-search.d.ts +25 -0
- package/dist/tools/web-search.js +68 -6
- package/dist/tools/web-search.js.map +1 -1
- package/dist/utils/config-validation/schema.d.ts +2 -2
- package/dist/utils/debug-logger.d.ts +1 -1
- package/dist/utils/rtk-compressor.d.ts +13 -10
- package/dist/utils/rtk-compressor.js +83 -34
- package/dist/utils/rtk-compressor.js.map +1 -1
- package/dist/utils/stable-json.d.ts +27 -0
- package/dist/utils/stable-json.js +50 -0
- package/dist/utils/stable-json.js.map +1 -0
- package/dist/webhooks/webhook-manager.d.ts +7 -0
- package/dist/webhooks/webhook-manager.js +29 -0
- package/dist/webhooks/webhook-manager.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restorable Compression — Manus AI context engineering pattern
|
|
3
|
+
*
|
|
4
|
+
* Instead of lossy summarisation (which discards content permanently),
|
|
5
|
+
* this module extracts structural identifiers (file paths, URLs, tool
|
|
6
|
+
* call IDs, line ranges) from messages that are about to be dropped,
|
|
7
|
+
* then stores the original content indexed by those identifiers.
|
|
8
|
+
*
|
|
9
|
+
* The agent can later call `restore_context(identifier)` to re-fetch
|
|
10
|
+
* the full content on demand, making context compression reversible.
|
|
11
|
+
*
|
|
12
|
+
* This is complementary to summarisation: a short summary of a long
|
|
13
|
+
* file-read result is kept in the context, while the full content is
|
|
14
|
+
* recoverable via its file path identifier.
|
|
15
|
+
*
|
|
16
|
+
* Ref: "Context Engineering for AI Agents: Lessons from Building Manus"
|
|
17
|
+
* https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus
|
|
18
|
+
*/
|
|
19
|
+
export interface CompressibleMessage {
|
|
20
|
+
role: string;
|
|
21
|
+
content: string | null;
|
|
22
|
+
tool_call_id?: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CompressionResult {
|
|
26
|
+
/** Compressed messages (identifiers preserved, full content dropped) */
|
|
27
|
+
messages: CompressibleMessage[];
|
|
28
|
+
/** Identifiers that were extracted and stored */
|
|
29
|
+
identifiers: string[];
|
|
30
|
+
/** Number of tokens saved (estimated) */
|
|
31
|
+
tokensSaved: number;
|
|
32
|
+
}
|
|
33
|
+
export interface RestoreResult {
|
|
34
|
+
found: boolean;
|
|
35
|
+
content: string;
|
|
36
|
+
identifier: string;
|
|
37
|
+
}
|
|
38
|
+
export declare class RestorableCompressor {
|
|
39
|
+
/** identifier → original content */
|
|
40
|
+
private store;
|
|
41
|
+
/**
|
|
42
|
+
* Compress a slice of messages that are about to be dropped.
|
|
43
|
+
*
|
|
44
|
+
* For each message, identifiers are extracted and the full content is
|
|
45
|
+
* stored. The message content is replaced with a compact stub listing
|
|
46
|
+
* the available identifiers.
|
|
47
|
+
*/
|
|
48
|
+
compress(messages: CompressibleMessage[]): CompressionResult;
|
|
49
|
+
/**
|
|
50
|
+
* Restore the original content for an identifier.
|
|
51
|
+
*
|
|
52
|
+
* For file path identifiers, attempts to read from disk as a fallback.
|
|
53
|
+
* For URLs, returns a hint to use web_fetch.
|
|
54
|
+
*/
|
|
55
|
+
restore(identifier: string): RestoreResult;
|
|
56
|
+
/**
|
|
57
|
+
* Persist a tool result to disk under `.codebuddy/tool-results/<callId>.txt`.
|
|
58
|
+
* This gives the restore_context tool a reliable disk-backed source and enables
|
|
59
|
+
* the compact/full dual-representation pattern (Manus AI #19).
|
|
60
|
+
*
|
|
61
|
+
* @param callId - Tool call ID (e.g. call_abc123 or toolu_xyz)
|
|
62
|
+
* @param content - Full tool output
|
|
63
|
+
* @param workDir - Working directory (defaults to process.cwd())
|
|
64
|
+
*/
|
|
65
|
+
writeToolResult(callId: string, content: string, workDir?: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Read a tool result from disk (`.codebuddy/tool-results/<callId>.txt`).
|
|
68
|
+
* Used by restore_context when the in-memory store has been evicted.
|
|
69
|
+
*/
|
|
70
|
+
private readToolResultFromDisk;
|
|
71
|
+
/** List all stored identifiers */
|
|
72
|
+
listIdentifiers(): string[];
|
|
73
|
+
/** Total number of bytes stored */
|
|
74
|
+
storeSize(): number;
|
|
75
|
+
/** Evict oldest entries if store exceeds maxBytes (default 10 MB) */
|
|
76
|
+
evict(maxBytes?: number): void;
|
|
77
|
+
}
|
|
78
|
+
export declare function getRestorableCompressor(): RestorableCompressor;
|
|
79
|
+
/** Reset singleton (for tests) */
|
|
80
|
+
export declare function resetRestorableCompressor(): void;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restorable Compression — Manus AI context engineering pattern
|
|
3
|
+
*
|
|
4
|
+
* Instead of lossy summarisation (which discards content permanently),
|
|
5
|
+
* this module extracts structural identifiers (file paths, URLs, tool
|
|
6
|
+
* call IDs, line ranges) from messages that are about to be dropped,
|
|
7
|
+
* then stores the original content indexed by those identifiers.
|
|
8
|
+
*
|
|
9
|
+
* The agent can later call `restore_context(identifier)` to re-fetch
|
|
10
|
+
* the full content on demand, making context compression reversible.
|
|
11
|
+
*
|
|
12
|
+
* This is complementary to summarisation: a short summary of a long
|
|
13
|
+
* file-read result is kept in the context, while the full content is
|
|
14
|
+
* recoverable via its file path identifier.
|
|
15
|
+
*
|
|
16
|
+
* Ref: "Context Engineering for AI Agents: Lessons from Building Manus"
|
|
17
|
+
* https://manus.im/blog/Context-Engineering-for-AI-Agents-Lessons-from-Building-Manus
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'fs';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { logger } from '../utils/logger.js';
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Identifier extractors
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// File paths: absolute or relative, with extensions
|
|
26
|
+
const FILE_PATH_RE = /(?:^|\s|["'`(])(\/?(?:[\w.-]+\/)*[\w.-]+\.(?:ts|js|py|json|md|txt|yaml|yml|sh|go|rs|java|cpp|c|h|rb|php|swift|kt|cs|html|css|sql|env|toml|cfg|conf|xml)(?::\d+(?:-\d+)?)?)/g;
|
|
27
|
+
// URLs
|
|
28
|
+
const URL_RE = /https?:\/\/[^\s"'<>)]+/g;
|
|
29
|
+
// Tool call IDs (Anthropic/OpenAI style)
|
|
30
|
+
const TOOL_CALL_ID_RE = /\b(call_[a-zA-Z0-9]+|toolu_[a-zA-Z0-9]+)\b/g;
|
|
31
|
+
function extractIdentifiers(text) {
|
|
32
|
+
const ids = new Set();
|
|
33
|
+
for (const m of text.matchAll(FILE_PATH_RE)) {
|
|
34
|
+
const raw = m[1].trim().replace(/['"`:]/g, '');
|
|
35
|
+
if (raw.length > 3)
|
|
36
|
+
ids.add(raw);
|
|
37
|
+
}
|
|
38
|
+
for (const m of text.matchAll(URL_RE)) {
|
|
39
|
+
const url = m[0].replace(/[.,;)]+$/, ''); // strip trailing punctuation
|
|
40
|
+
ids.add(url);
|
|
41
|
+
}
|
|
42
|
+
for (const m of text.matchAll(TOOL_CALL_ID_RE)) {
|
|
43
|
+
ids.add(m[1]);
|
|
44
|
+
}
|
|
45
|
+
return [...ids];
|
|
46
|
+
}
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// RestorableCompressor
|
|
49
|
+
// ============================================================================
|
|
50
|
+
export class RestorableCompressor {
|
|
51
|
+
/** identifier → original content */
|
|
52
|
+
store = new Map();
|
|
53
|
+
/**
|
|
54
|
+
* Compress a slice of messages that are about to be dropped.
|
|
55
|
+
*
|
|
56
|
+
* For each message, identifiers are extracted and the full content is
|
|
57
|
+
* stored. The message content is replaced with a compact stub listing
|
|
58
|
+
* the available identifiers.
|
|
59
|
+
*/
|
|
60
|
+
compress(messages) {
|
|
61
|
+
const compressed = [];
|
|
62
|
+
const allIdentifiers = [];
|
|
63
|
+
let tokensSaved = 0;
|
|
64
|
+
for (const msg of messages) {
|
|
65
|
+
const content = msg.content ?? '';
|
|
66
|
+
if (!content || content.length < 200) {
|
|
67
|
+
// Short messages: keep as-is
|
|
68
|
+
compressed.push(msg);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const ids = extractIdentifiers(content);
|
|
72
|
+
if (ids.length === 0) {
|
|
73
|
+
// No identifiers to preserve — keep original
|
|
74
|
+
compressed.push(msg);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// Store original content indexed by each identifier
|
|
78
|
+
for (const id of ids) {
|
|
79
|
+
if (!this.store.has(id)) {
|
|
80
|
+
this.store.set(id, content);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
allIdentifiers.push(...ids);
|
|
84
|
+
tokensSaved += Math.floor(content.length / 4); // rough token estimate
|
|
85
|
+
// Replace with a compact stub
|
|
86
|
+
const stub = `[Content compressed — identifiers: ${ids.slice(0, 5).join(', ')}${ids.length > 5 ? ` +${ids.length - 5} more` : ''}. Use restore_context(identifier) to retrieve.]`;
|
|
87
|
+
compressed.push({ ...msg, content: stub });
|
|
88
|
+
logger.debug('RestorableCompressor: compressed message', {
|
|
89
|
+
identifiers: ids.length,
|
|
90
|
+
originalLen: content.length,
|
|
91
|
+
stubLen: stub.length,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
messages: compressed,
|
|
96
|
+
identifiers: [...new Set(allIdentifiers)],
|
|
97
|
+
tokensSaved,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Restore the original content for an identifier.
|
|
102
|
+
*
|
|
103
|
+
* For file path identifiers, attempts to read from disk as a fallback.
|
|
104
|
+
* For URLs, returns a hint to use web_fetch.
|
|
105
|
+
*/
|
|
106
|
+
restore(identifier) {
|
|
107
|
+
// 1. Check in-memory store
|
|
108
|
+
const stored = this.store.get(identifier);
|
|
109
|
+
if (stored) {
|
|
110
|
+
return { found: true, content: stored, identifier };
|
|
111
|
+
}
|
|
112
|
+
// 2. Tool call ID — check disk-backed store
|
|
113
|
+
if (identifier.startsWith('call_') || identifier.startsWith('toulu_') || identifier.startsWith('toolu_')) {
|
|
114
|
+
const diskContent = this.readToolResultFromDisk(identifier);
|
|
115
|
+
if (diskContent) {
|
|
116
|
+
return { found: true, content: diskContent, identifier };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// 3. File path fallback — try reading from disk
|
|
120
|
+
if (!identifier.startsWith('http') && !identifier.startsWith('call_') && !identifier.startsWith('toolu_')) {
|
|
121
|
+
try {
|
|
122
|
+
// Strip line range if present (file.ts:10-50 → file.ts)
|
|
123
|
+
const filePath = identifier.split(':')[0];
|
|
124
|
+
if (fs.existsSync(filePath)) {
|
|
125
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
126
|
+
this.store.set(identifier, content); // cache for future
|
|
127
|
+
return { found: true, content, identifier };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// ignore
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// 3. URL hint
|
|
135
|
+
if (identifier.startsWith('http')) {
|
|
136
|
+
return {
|
|
137
|
+
found: false,
|
|
138
|
+
content: `URL content not cached. Use web_fetch("${identifier}") to retrieve it.`,
|
|
139
|
+
identifier,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
found: false,
|
|
144
|
+
content: `Identifier "${identifier}" not found in restoration store.`,
|
|
145
|
+
identifier,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Persist a tool result to disk under `.codebuddy/tool-results/<callId>.txt`.
|
|
150
|
+
* This gives the restore_context tool a reliable disk-backed source and enables
|
|
151
|
+
* the compact/full dual-representation pattern (Manus AI #19).
|
|
152
|
+
*
|
|
153
|
+
* @param callId - Tool call ID (e.g. call_abc123 or toolu_xyz)
|
|
154
|
+
* @param content - Full tool output
|
|
155
|
+
* @param workDir - Working directory (defaults to process.cwd())
|
|
156
|
+
*/
|
|
157
|
+
writeToolResult(callId, content, workDir = process.cwd()) {
|
|
158
|
+
try {
|
|
159
|
+
const dir = path.join(workDir, '.codebuddy', 'tool-results');
|
|
160
|
+
if (!fs.existsSync(dir)) {
|
|
161
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
162
|
+
}
|
|
163
|
+
const filePath = path.join(dir, `${callId}.txt`);
|
|
164
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
165
|
+
// Also store in memory for fast access
|
|
166
|
+
this.store.set(callId, content);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
// Non-critical: disk write failure should not break tool execution
|
|
170
|
+
logger.debug('RestorableCompressor: failed to write tool result to disk', { callId, err });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Read a tool result from disk (`.codebuddy/tool-results/<callId>.txt`).
|
|
175
|
+
* Used by restore_context when the in-memory store has been evicted.
|
|
176
|
+
*/
|
|
177
|
+
readToolResultFromDisk(callId, workDir = process.cwd()) {
|
|
178
|
+
try {
|
|
179
|
+
const filePath = path.join(workDir, '.codebuddy', 'tool-results', `${callId}.txt`);
|
|
180
|
+
if (fs.existsSync(filePath)) {
|
|
181
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
182
|
+
this.store.set(callId, content); // cache back into memory
|
|
183
|
+
return content;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// ignore
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
/** List all stored identifiers */
|
|
192
|
+
listIdentifiers() {
|
|
193
|
+
return [...this.store.keys()];
|
|
194
|
+
}
|
|
195
|
+
/** Total number of bytes stored */
|
|
196
|
+
storeSize() {
|
|
197
|
+
let total = 0;
|
|
198
|
+
for (const v of this.store.values())
|
|
199
|
+
total += v.length;
|
|
200
|
+
return total;
|
|
201
|
+
}
|
|
202
|
+
/** Evict oldest entries if store exceeds maxBytes (default 10 MB) */
|
|
203
|
+
evict(maxBytes = 10 * 1024 * 1024) {
|
|
204
|
+
while (this.storeSize() > maxBytes && this.store.size > 0) {
|
|
205
|
+
const firstKey = this.store.keys().next().value;
|
|
206
|
+
if (firstKey !== undefined) {
|
|
207
|
+
this.store.delete(firstKey);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// ============================================================================
|
|
216
|
+
// Singleton
|
|
217
|
+
// ============================================================================
|
|
218
|
+
let _instance = null;
|
|
219
|
+
export function getRestorableCompressor() {
|
|
220
|
+
if (!_instance)
|
|
221
|
+
_instance = new RestorableCompressor();
|
|
222
|
+
return _instance;
|
|
223
|
+
}
|
|
224
|
+
/** Reset singleton (for tests) */
|
|
225
|
+
export function resetRestorableCompressor() {
|
|
226
|
+
_instance = null;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=restorable-compression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restorable-compression.js","sourceRoot":"","sources":["../../src/context/restorable-compression.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daily Session Reset — OpenClaw-inspired context boundary
|
|
3
|
+
*
|
|
4
|
+
* Automatically resets the conversation context at a configurable time
|
|
5
|
+
* each day (default: 04:00 local time). This prevents unbounded context
|
|
6
|
+
* growth in long-running daemon sessions and mirrors the daily boundary
|
|
7
|
+
* reset pattern in OpenClaw.
|
|
8
|
+
*
|
|
9
|
+
* What is reset:
|
|
10
|
+
* - In-memory conversation history (messages array)
|
|
11
|
+
* - Cached tool selection results
|
|
12
|
+
*
|
|
13
|
+
* What is PRESERVED:
|
|
14
|
+
* - MEMORY.md (durable facts)
|
|
15
|
+
* - HEARTBEAT.md (task checklist)
|
|
16
|
+
* - Session metadata (model, cost counters)
|
|
17
|
+
* - All files on disk (todo.md, PLAN.md, etc.)
|
|
18
|
+
*
|
|
19
|
+
* After reset the agent posts a summary message noting the daily boundary
|
|
20
|
+
* so the conversation log remains intelligible.
|
|
21
|
+
*
|
|
22
|
+
* Ref: OpenClaw session management compaction docs
|
|
23
|
+
* https://docs.openclaw.ai/reference/session-management-compaction
|
|
24
|
+
*/
|
|
25
|
+
import { EventEmitter } from 'events';
|
|
26
|
+
export interface DailyResetConfig {
|
|
27
|
+
/** Hour of the day for the reset (0-23). Default: 4 */
|
|
28
|
+
resetHour: number;
|
|
29
|
+
/** Minute of the reset (0-59). Default: 0 */
|
|
30
|
+
resetMinute: number;
|
|
31
|
+
/** IANA timezone identifier. Default: system local */
|
|
32
|
+
timezone?: string;
|
|
33
|
+
/** Whether the daily reset is enabled. Default: true */
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
/** Post a summary message after reset. Default: true */
|
|
36
|
+
postSummary: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface ResetResult {
|
|
39
|
+
triggeredAt: Date;
|
|
40
|
+
/** Number of messages cleared */
|
|
41
|
+
messagesCleared: number;
|
|
42
|
+
/** Summary message posted to conversation (or null if postSummary is false) */
|
|
43
|
+
summaryMessage: string | null;
|
|
44
|
+
}
|
|
45
|
+
export declare class DailyResetManager extends EventEmitter {
|
|
46
|
+
private config;
|
|
47
|
+
private timer;
|
|
48
|
+
private lastResetDate;
|
|
49
|
+
constructor(config?: Partial<DailyResetConfig>);
|
|
50
|
+
/**
|
|
51
|
+
* Start the daily reset scheduler.
|
|
52
|
+
* Call this once when the daemon starts.
|
|
53
|
+
*/
|
|
54
|
+
start(): void;
|
|
55
|
+
stop(): void;
|
|
56
|
+
/** Returns milliseconds until the next reset window. */
|
|
57
|
+
msUntilNextReset(): number;
|
|
58
|
+
private scheduleNext;
|
|
59
|
+
/**
|
|
60
|
+
* Perform the daily reset on the provided messages array (modified in-place).
|
|
61
|
+
*
|
|
62
|
+
* @param messages - The agent's LLM messages array to clear
|
|
63
|
+
* @param systemMessage - Optional system message to keep at position [0]
|
|
64
|
+
*/
|
|
65
|
+
runReset(messages: Array<{
|
|
66
|
+
role: string;
|
|
67
|
+
content: string | null;
|
|
68
|
+
}>, systemMessage?: {
|
|
69
|
+
role: string;
|
|
70
|
+
content: string;
|
|
71
|
+
}): Promise<ResetResult>;
|
|
72
|
+
private buildSummaryMessage;
|
|
73
|
+
getConfig(): Readonly<DailyResetConfig>;
|
|
74
|
+
isEnabled(): boolean;
|
|
75
|
+
}
|
|
76
|
+
export declare function getDailyResetManager(config?: Partial<DailyResetConfig>): DailyResetManager;
|
|
77
|
+
export declare function resetDailyResetManager(): void;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daily Session Reset — OpenClaw-inspired context boundary
|
|
3
|
+
*
|
|
4
|
+
* Automatically resets the conversation context at a configurable time
|
|
5
|
+
* each day (default: 04:00 local time). This prevents unbounded context
|
|
6
|
+
* growth in long-running daemon sessions and mirrors the daily boundary
|
|
7
|
+
* reset pattern in OpenClaw.
|
|
8
|
+
*
|
|
9
|
+
* What is reset:
|
|
10
|
+
* - In-memory conversation history (messages array)
|
|
11
|
+
* - Cached tool selection results
|
|
12
|
+
*
|
|
13
|
+
* What is PRESERVED:
|
|
14
|
+
* - MEMORY.md (durable facts)
|
|
15
|
+
* - HEARTBEAT.md (task checklist)
|
|
16
|
+
* - Session metadata (model, cost counters)
|
|
17
|
+
* - All files on disk (todo.md, PLAN.md, etc.)
|
|
18
|
+
*
|
|
19
|
+
* After reset the agent posts a summary message noting the daily boundary
|
|
20
|
+
* so the conversation log remains intelligible.
|
|
21
|
+
*
|
|
22
|
+
* Ref: OpenClaw session management compaction docs
|
|
23
|
+
* https://docs.openclaw.ai/reference/session-management-compaction
|
|
24
|
+
*/
|
|
25
|
+
import { EventEmitter } from 'events';
|
|
26
|
+
import { logger } from '../utils/logger.js';
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// DailyResetManager
|
|
29
|
+
// ============================================================================
|
|
30
|
+
export class DailyResetManager extends EventEmitter {
|
|
31
|
+
config;
|
|
32
|
+
timer = null;
|
|
33
|
+
lastResetDate = null; // 'YYYY-MM-DD'
|
|
34
|
+
constructor(config = {}) {
|
|
35
|
+
super();
|
|
36
|
+
this.config = {
|
|
37
|
+
resetHour: config.resetHour ?? 4,
|
|
38
|
+
resetMinute: config.resetMinute ?? 0,
|
|
39
|
+
timezone: config.timezone,
|
|
40
|
+
enabled: config.enabled ?? true,
|
|
41
|
+
postSummary: config.postSummary ?? true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// --------------------------------------------------------------------------
|
|
45
|
+
// Lifecycle
|
|
46
|
+
// --------------------------------------------------------------------------
|
|
47
|
+
/**
|
|
48
|
+
* Start the daily reset scheduler.
|
|
49
|
+
* Call this once when the daemon starts.
|
|
50
|
+
*/
|
|
51
|
+
start() {
|
|
52
|
+
if (!this.config.enabled)
|
|
53
|
+
return;
|
|
54
|
+
this.scheduleNext();
|
|
55
|
+
logger.debug('DailyResetManager started', {
|
|
56
|
+
resetHour: this.config.resetHour,
|
|
57
|
+
resetMinute: this.config.resetMinute,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
stop() {
|
|
61
|
+
if (this.timer) {
|
|
62
|
+
clearTimeout(this.timer);
|
|
63
|
+
this.timer = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// --------------------------------------------------------------------------
|
|
67
|
+
// Scheduling
|
|
68
|
+
// --------------------------------------------------------------------------
|
|
69
|
+
/** Returns milliseconds until the next reset window. */
|
|
70
|
+
msUntilNextReset() {
|
|
71
|
+
const now = new Date();
|
|
72
|
+
const next = new Date(now);
|
|
73
|
+
next.setHours(this.config.resetHour, this.config.resetMinute, 0, 0);
|
|
74
|
+
if (next <= now) {
|
|
75
|
+
// Already past today's reset time — schedule for tomorrow
|
|
76
|
+
next.setDate(next.getDate() + 1);
|
|
77
|
+
}
|
|
78
|
+
return next.getTime() - now.getTime();
|
|
79
|
+
}
|
|
80
|
+
scheduleNext() {
|
|
81
|
+
const ms = this.msUntilNextReset();
|
|
82
|
+
logger.debug('DailyResetManager: next reset in', {
|
|
83
|
+
minutes: Math.round(ms / 60_000),
|
|
84
|
+
});
|
|
85
|
+
this.timer = setTimeout(() => {
|
|
86
|
+
this.runReset([]).catch(err => {
|
|
87
|
+
logger.error('DailyResetManager: reset failed', { err });
|
|
88
|
+
});
|
|
89
|
+
this.scheduleNext(); // reschedule for tomorrow
|
|
90
|
+
}, ms);
|
|
91
|
+
// Allow Node to exit if this is the only pending timer
|
|
92
|
+
if (this.timer.unref)
|
|
93
|
+
this.timer.unref();
|
|
94
|
+
}
|
|
95
|
+
// --------------------------------------------------------------------------
|
|
96
|
+
// Reset logic
|
|
97
|
+
// --------------------------------------------------------------------------
|
|
98
|
+
/**
|
|
99
|
+
* Perform the daily reset on the provided messages array (modified in-place).
|
|
100
|
+
*
|
|
101
|
+
* @param messages - The agent's LLM messages array to clear
|
|
102
|
+
* @param systemMessage - Optional system message to keep at position [0]
|
|
103
|
+
*/
|
|
104
|
+
async runReset(messages, systemMessage) {
|
|
105
|
+
const today = new Date().toISOString().split('T')[0];
|
|
106
|
+
// Avoid duplicate resets on the same day
|
|
107
|
+
if (this.lastResetDate === today) {
|
|
108
|
+
return {
|
|
109
|
+
triggeredAt: new Date(),
|
|
110
|
+
messagesCleared: 0,
|
|
111
|
+
summaryMessage: null,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
this.lastResetDate = today;
|
|
115
|
+
const messagesCleared = messages.length;
|
|
116
|
+
// Clear messages (in-place)
|
|
117
|
+
messages.splice(0, messages.length);
|
|
118
|
+
// Re-inject system message if provided
|
|
119
|
+
if (systemMessage) {
|
|
120
|
+
messages.push(systemMessage);
|
|
121
|
+
}
|
|
122
|
+
const summaryMessage = this.config.postSummary
|
|
123
|
+
? this.buildSummaryMessage(today, messagesCleared)
|
|
124
|
+
: null;
|
|
125
|
+
if (summaryMessage && messages.length > 0) {
|
|
126
|
+
// Append the summary as an assistant message so it appears in the log
|
|
127
|
+
messages.push({ role: 'assistant', content: summaryMessage });
|
|
128
|
+
}
|
|
129
|
+
const result = {
|
|
130
|
+
triggeredAt: new Date(),
|
|
131
|
+
messagesCleared,
|
|
132
|
+
summaryMessage,
|
|
133
|
+
};
|
|
134
|
+
this.emit('reset', result);
|
|
135
|
+
logger.info('DailyResetManager: daily reset completed', {
|
|
136
|
+
date: today,
|
|
137
|
+
messagesCleared,
|
|
138
|
+
});
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
// --------------------------------------------------------------------------
|
|
142
|
+
// Helpers
|
|
143
|
+
// --------------------------------------------------------------------------
|
|
144
|
+
buildSummaryMessage(date, cleared) {
|
|
145
|
+
return [
|
|
146
|
+
`---`,
|
|
147
|
+
`**[Daily context boundary — ${date}]**`,
|
|
148
|
+
`Conversation history was automatically cleared at ${String(this.config.resetHour).padStart(2, '0')}:${String(this.config.resetMinute).padStart(2, '0')} to maintain a fresh context window.`,
|
|
149
|
+
`${cleared} messages from the previous session were cleared.`,
|
|
150
|
+
`MEMORY.md, HEARTBEAT.md, todo.md, and all project files are preserved.`,
|
|
151
|
+
`---`,
|
|
152
|
+
].join('\n');
|
|
153
|
+
}
|
|
154
|
+
getConfig() {
|
|
155
|
+
return { ...this.config };
|
|
156
|
+
}
|
|
157
|
+
isEnabled() {
|
|
158
|
+
return this.config.enabled;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Singleton
|
|
163
|
+
// ============================================================================
|
|
164
|
+
let _instance = null;
|
|
165
|
+
export function getDailyResetManager(config) {
|
|
166
|
+
if (!_instance) {
|
|
167
|
+
_instance = new DailyResetManager(config);
|
|
168
|
+
}
|
|
169
|
+
return _instance;
|
|
170
|
+
}
|
|
171
|
+
export function resetDailyResetManager() {
|
|
172
|
+
_instance?.stop();
|
|
173
|
+
_instance = null;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=daily-reset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daily-reset.js","sourceRoot":"","sources":["../../src/daemon/daily-reset.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon/index.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export { DaemonManager, getDaemonManager, resetDaemonManager, type DaemonConfig,
|
|
|
5
5
|
export { DaemonLifecycle, getDaemonLifecycle, resetDaemonLifecycle, type DaemonService, type LifecycleConfig, } from './daemon-lifecycle.js';
|
|
6
6
|
export { CronAgentBridge, getCronAgentBridge, resetCronAgentBridge, type BridgeConfig, type JobExecutionResult, } from './cron-agent-bridge.js';
|
|
7
7
|
export { HealthMonitor, getHealthMonitor, resetHealthMonitor, type HealthMetrics, type HealthMonitorConfig, } from './health-monitor.js';
|
|
8
|
+
export { DailyResetManager, getDailyResetManager, resetDailyResetManager, type DailyResetConfig, type ResetResult, } from './daily-reset.js';
|
package/dist/daemon/index.js
CHANGED
|
@@ -5,4 +5,5 @@ export { DaemonManager, getDaemonManager, resetDaemonManager, } from './daemon-m
|
|
|
5
5
|
export { DaemonLifecycle, getDaemonLifecycle, resetDaemonLifecycle, } from './daemon-lifecycle.js';
|
|
6
6
|
export { CronAgentBridge, getCronAgentBridge, resetCronAgentBridge, } from './cron-agent-bridge.js';
|
|
7
7
|
export { HealthMonitor, getHealthMonitor, resetHealthMonitor, } from './health-monitor.js';
|
|
8
|
+
export { DailyResetManager, getDailyResetManager, resetDailyResetManager, } from './daily-reset.js';
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/daemon/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GAInB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GAGnB,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GAInB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GAGnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GAGvB,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -581,8 +581,21 @@ program
|
|
|
581
581
|
.option("--append-system-prompt <text>", "append text to the default system prompt")
|
|
582
582
|
.option("--append-system-prompt-file <path>", "append file contents to the default system prompt")
|
|
583
583
|
.option("--fallback-model <model>", "auto-fallback model when default is overloaded")
|
|
584
|
+
.option("--profile <name>", "apply a named configuration profile from .codebuddy/config.toml [profiles.<name>]")
|
|
584
585
|
.option("--from-pr <pr>", "link session to a GitHub pull request (number or URL)")
|
|
585
586
|
.action(async (message, options) => {
|
|
587
|
+
// Apply named configuration profile (--profile <name>) before anything else
|
|
588
|
+
if (options.profile) {
|
|
589
|
+
try {
|
|
590
|
+
const { getConfigManager } = await import('./config/toml-config.js');
|
|
591
|
+
getConfigManager().load();
|
|
592
|
+
getConfigManager().applyProfile(options.profile);
|
|
593
|
+
}
|
|
594
|
+
catch (err) {
|
|
595
|
+
startupLogger.error(`Profile error: ${err instanceof Error ? err.message : err}`);
|
|
596
|
+
process.exit(1);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
586
599
|
// Handle --setup flag (interactive setup wizard)
|
|
587
600
|
if (options.setup) {
|
|
588
601
|
const { runSetup } = await import("./utils/interactive-setup.js");
|
|
@@ -1257,5 +1270,45 @@ addLazyCommandGroup(program, 'config', 'Show environment variable configuration
|
|
|
1257
1270
|
const { registerConfigCommand } = await import('./commands/cli/config-command.js');
|
|
1258
1271
|
registerConfigCommand(program);
|
|
1259
1272
|
});
|
|
1273
|
+
// Dev workflows — plan, run, pr, fix-ci, explain
|
|
1274
|
+
addLazyCommandGroup(program, 'dev', 'Golden-path developer workflows (plan, run, pr, fix-ci, explain)', async () => {
|
|
1275
|
+
const { registerDevCommands } = await import('./commands/dev/index.js');
|
|
1276
|
+
registerDevCommands(program);
|
|
1277
|
+
});
|
|
1278
|
+
// Run observability — list, show, tail, replay
|
|
1279
|
+
addLazyCommandGroup(program, 'runs', 'Inspect and replay agent runs (observability)', async () => {
|
|
1280
|
+
const { registerRunCommands } = await import('./commands/run-cli/index.js');
|
|
1281
|
+
registerRunCommands(program);
|
|
1282
|
+
});
|
|
1283
|
+
// DM pairing — approve, revoke, list, pending
|
|
1284
|
+
addLazyCommand(program, 'pairing', 'Manage DM pairing security (allowlist for messaging channel senders)', async () => {
|
|
1285
|
+
const { createPairingCommand } = await import('./commands/pairing.js');
|
|
1286
|
+
return createPairingCommand();
|
|
1287
|
+
});
|
|
1288
|
+
// Knowledge base management — add, list, show, search, remove, context
|
|
1289
|
+
addLazyCommand(program, 'knowledge', 'Manage agent knowledge bases (Knowledge.md files injected as context)', async () => {
|
|
1290
|
+
const { createKnowledgeCommand } = await import('./commands/knowledge.js');
|
|
1291
|
+
return createKnowledgeCommand();
|
|
1292
|
+
});
|
|
1293
|
+
// Wide Research — parallel agent workers for comprehensive research
|
|
1294
|
+
addLazyCommand(program, 'research', 'Wide Research: spawn parallel agent workers to research a topic (Manus AI-inspired)', async () => {
|
|
1295
|
+
const { createResearchCommand } = await import('./commands/research/index.js');
|
|
1296
|
+
return createResearchCommand();
|
|
1297
|
+
});
|
|
1298
|
+
// Todo attention bias — Manus AI-inspired persistent task list
|
|
1299
|
+
addLazyCommand(program, 'todo', 'Manage persistent task list (todo.md) — injected at end of every agent turn for focus', async () => {
|
|
1300
|
+
const { createTodosCommand } = await import('./commands/todos.js');
|
|
1301
|
+
return createTodosCommand();
|
|
1302
|
+
});
|
|
1303
|
+
// Exec Policy — Codex-inspired command authorization (allow/deny/ask/sandbox + prefix rules)
|
|
1304
|
+
addLazyCommand(program, 'execpolicy', 'Manage execution policy rules (allow/deny/ask/sandbox) for shell commands', async () => {
|
|
1305
|
+
const { createExecPolicyCommand } = await import('./commands/execpolicy.js');
|
|
1306
|
+
return createExecPolicyCommand();
|
|
1307
|
+
});
|
|
1308
|
+
// Lessons — self-improvement loop (lessons learned injected per agent turn)
|
|
1309
|
+
addLazyCommand(program, 'lessons', 'Manage lessons learned — self-improvement loop for recurring patterns (injected every turn)', async () => {
|
|
1310
|
+
const { createLessonsCommand } = await import('./commands/lessons.js');
|
|
1311
|
+
return createLessonsCommand();
|
|
1312
|
+
});
|
|
1260
1313
|
program.parse();
|
|
1261
1314
|
//# sourceMappingURL=index.js.map
|