opencarly 1.0.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 (59) hide show
  1. package/README.md +78 -0
  2. package/bin/install.js +304 -0
  3. package/commands/carly-manager.md +69 -0
  4. package/dist/config/discovery.d.ts +22 -0
  5. package/dist/config/discovery.d.ts.map +1 -0
  6. package/dist/config/discovery.js +43 -0
  7. package/dist/config/discovery.js.map +1 -0
  8. package/dist/config/index.d.ts +7 -0
  9. package/dist/config/index.d.ts.map +1 -0
  10. package/dist/config/index.js +7 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/config/manifest.d.ts +39 -0
  13. package/dist/config/manifest.d.ts.map +1 -0
  14. package/dist/config/manifest.js +139 -0
  15. package/dist/config/manifest.js.map +1 -0
  16. package/dist/config/schema.d.ts +663 -0
  17. package/dist/config/schema.d.ts.map +1 -0
  18. package/dist/config/schema.js +208 -0
  19. package/dist/config/schema.js.map +1 -0
  20. package/dist/engine/brackets.d.ts +26 -0
  21. package/dist/engine/brackets.d.ts.map +1 -0
  22. package/dist/engine/brackets.js +49 -0
  23. package/dist/engine/brackets.js.map +1 -0
  24. package/dist/engine/index.d.ts +8 -0
  25. package/dist/engine/index.d.ts.map +1 -0
  26. package/dist/engine/index.js +8 -0
  27. package/dist/engine/index.js.map +1 -0
  28. package/dist/engine/loader.d.ts +82 -0
  29. package/dist/engine/loader.d.ts.map +1 -0
  30. package/dist/engine/loader.js +147 -0
  31. package/dist/engine/loader.js.map +1 -0
  32. package/dist/engine/matcher.d.ts +43 -0
  33. package/dist/engine/matcher.d.ts.map +1 -0
  34. package/dist/engine/matcher.js +174 -0
  35. package/dist/engine/matcher.js.map +1 -0
  36. package/dist/engine/trimmer.d.ts +91 -0
  37. package/dist/engine/trimmer.d.ts.map +1 -0
  38. package/dist/engine/trimmer.js +236 -0
  39. package/dist/engine/trimmer.js.map +1 -0
  40. package/dist/formatter/formatter.d.ts +23 -0
  41. package/dist/formatter/formatter.d.ts.map +1 -0
  42. package/dist/formatter/formatter.js +129 -0
  43. package/dist/formatter/formatter.js.map +1 -0
  44. package/dist/index.d.ts +15 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +484 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/session/session.d.ts +60 -0
  49. package/dist/session/session.d.ts.map +1 -0
  50. package/dist/session/session.js +394 -0
  51. package/dist/session/session.js.map +1 -0
  52. package/package.json +59 -0
  53. package/templates/.opencarly/commands.json +96 -0
  54. package/templates/.opencarly/context.json +44 -0
  55. package/templates/.opencarly/domains/development.md +13 -0
  56. package/templates/.opencarly/domains/global.md +13 -0
  57. package/templates/.opencarly/domains/security.md +14 -0
  58. package/templates/.opencarly/domains/testing.md +12 -0
  59. package/templates/.opencarly/manifest.json +43 -0
@@ -0,0 +1,208 @@
1
+ /**
2
+ * OpenCarly Configuration Schemas
3
+ *
4
+ * Zod schemas for all configuration files:
5
+ * - manifest.json (domain registry, settings)
6
+ * - commands.json (star-command definitions)
7
+ * - context.json (context bracket thresholds and rules)
8
+ * - sessions/*.json (per-session state)
9
+ */
10
+ import { z } from "zod";
11
+ // ---------------------------------------------------------------------------
12
+ // Domain Configuration (inside manifest.json)
13
+ // ---------------------------------------------------------------------------
14
+ export const DomainConfigSchema = z.object({
15
+ /** Whether this domain is active */
16
+ state: z.enum(["active", "inactive"]).default("active"),
17
+ /** If true, domain rules load on every prompt (no keyword matching) */
18
+ alwaysOn: z.boolean().default(false),
19
+ /** Keywords that trigger this domain (substring match, case-insensitive) */
20
+ recall: z.array(z.string()).default([]),
21
+ /** Keywords that prevent this domain from loading */
22
+ exclude: z.array(z.string()).default([]),
23
+ /** File paths/globs that trigger this domain (e.g., ["*.tsx", "src/components/*"]) */
24
+ paths: z.array(z.string()).default([]),
25
+ /** Path to the domain rule file, relative to .opencarly/ */
26
+ file: z.string(),
27
+ });
28
+ // ---------------------------------------------------------------------------
29
+ // Manifest (manifest.json)
30
+ // ---------------------------------------------------------------------------
31
+ export const ManifestSchema = z.object({
32
+ /** Schema version for forward compatibility */
33
+ version: z.literal(1).default(1),
34
+ /** Enable DEVMODE debug output */
35
+ devmode: z.boolean().default(false),
36
+ /** Global exclusion keywords - if any match, skip ALL domain matching */
37
+ globalExclude: z.array(z.string()).default([]),
38
+ /** Domain definitions */
39
+ domains: z.record(z.string(), DomainConfigSchema).default({}),
40
+ /** Whether star-commands system is enabled */
41
+ commands: z
42
+ .object({
43
+ state: z.enum(["active", "inactive"]).default("active"),
44
+ })
45
+ .default({}),
46
+ /** Whether context bracket system is enabled */
47
+ context: z
48
+ .object({
49
+ state: z.enum(["active", "inactive"]).default("active"),
50
+ })
51
+ .default({}),
52
+ });
53
+ // ---------------------------------------------------------------------------
54
+ // Star-Command (commands.json)
55
+ // ---------------------------------------------------------------------------
56
+ export const StarCommandSchema = z.object({
57
+ /** Description of what this command does */
58
+ description: z.string().optional(),
59
+ /** Rules injected when this command is invoked */
60
+ rules: z.array(z.string()),
61
+ });
62
+ export const CommandsFileSchema = z.record(z.string(), StarCommandSchema);
63
+ // ---------------------------------------------------------------------------
64
+ // Context Brackets (context.json)
65
+ // ---------------------------------------------------------------------------
66
+ export const ContextBracketSchema = z.object({
67
+ /** Whether this bracket is enabled */
68
+ enabled: z.boolean().default(true),
69
+ /** Rules injected when this bracket is active */
70
+ rules: z.array(z.string()).default([]),
71
+ });
72
+ // ---------------------------------------------------------------------------
73
+ // Tool Output Trimming (inside context.json)
74
+ // ---------------------------------------------------------------------------
75
+ export const TrimmingConfigSchema = z.object({
76
+ /** Whether tool output trimming is enabled */
77
+ enabled: z.boolean().default(true),
78
+ /**
79
+ * Trimming aggressiveness mode:
80
+ * - conservative: only trims very stale/superseded outputs (threshold=20)
81
+ * - moderate: good balance of savings vs safety (threshold=40)
82
+ * - aggressive: trims most things beyond preserveLastN (threshold=60)
83
+ */
84
+ mode: z.enum(["conservative", "moderate", "aggressive"]).default("moderate"),
85
+ /** Hard floor: never trim tool outputs in the last N messages */
86
+ preserveLastN: z.number().min(1).default(3),
87
+ });
88
+ // ---------------------------------------------------------------------------
89
+ // Stats Tracking (inside context.json)
90
+ // ---------------------------------------------------------------------------
91
+ export const StatsConfigSchema = z.object({
92
+ /**
93
+ * Duration to track stats:
94
+ * - "all": All sessions (default)
95
+ * - "month": Only sessions from last 30 days
96
+ * - "week": Only sessions from last 7 days
97
+ */
98
+ trackDuration: z.enum(["all", "month", "week"]).default("all"),
99
+ });
100
+ /** Map trimming mode to score threshold */
101
+ export const TRIM_THRESHOLDS = {
102
+ conservative: 20,
103
+ moderate: 40,
104
+ aggressive: 60,
105
+ };
106
+ export const ContextFileSchema = z.object({
107
+ /** Prompt count thresholds for bracket transitions */
108
+ thresholds: z
109
+ .object({
110
+ moderate: z.number().default(15),
111
+ depleted: z.number().default(35),
112
+ critical: z.number().default(50),
113
+ })
114
+ .default({}),
115
+ /** Bracket definitions */
116
+ brackets: z
117
+ .object({
118
+ fresh: ContextBracketSchema.default({ enabled: true, rules: [] }),
119
+ moderate: ContextBracketSchema.default({ enabled: true, rules: [] }),
120
+ depleted: ContextBracketSchema.default({ enabled: true, rules: [] }),
121
+ })
122
+ .default({}),
123
+ /** Smart tool output trimming configuration */
124
+ trimming: TrimmingConfigSchema.default({}),
125
+ /** Token stats tracking configuration */
126
+ stats: StatsConfigSchema.default({}),
127
+ });
128
+ // ---------------------------------------------------------------------------
129
+ // Token Stats (tracked per session, persisted in session file)
130
+ // ---------------------------------------------------------------------------
131
+ export const TokenStatsSchema = z.object({
132
+ /** Total tokens saved by selective rule injection (all rules minus loaded rules) */
133
+ tokensSkippedBySelection: z.number().default(0),
134
+ /** Total tokens of rules actually injected into the system prompt */
135
+ tokensInjected: z.number().default(0),
136
+ /** Total tokens trimmed from conversation history (tool outputs) */
137
+ tokensTrimmedFromHistory: z.number().default(0),
138
+ /** Total tokens trimmed from stale <carly-rules> blocks in history */
139
+ tokensTrimmedCarlyBlocks: z.number().default(0),
140
+ /** Number of prompts processed */
141
+ promptsProcessed: z.number().default(0),
142
+ /** Number of rules injected across all prompts */
143
+ rulesInjected: z.number().default(0),
144
+ /** Baseline: tokens that would be used if all rules loaded every prompt */
145
+ baselineTokensPerPrompt: z.number().default(0),
146
+ });
147
+ // ---------------------------------------------------------------------------
148
+ // Cumulative Stats (persisted in stats.json)
149
+ // ---------------------------------------------------------------------------
150
+ export const CumulativeSessionSummarySchema = z.object({
151
+ sessionId: z.string(),
152
+ date: z.string(),
153
+ tokensSaved: z.number(),
154
+ promptsProcessed: z.number(),
155
+ tokensSkippedBySelection: z.number().default(0),
156
+ tokensTrimmedFromHistory: z.number().default(0),
157
+ tokensTrimmedCarlyBlocks: z.number().default(0),
158
+ tokensInjected: z.number().default(0),
159
+ rulesInjected: z.number().default(0),
160
+ });
161
+ export const CumulativeStatsSchema = z.object({
162
+ version: z.number().default(1),
163
+ cumulative: z
164
+ .object({
165
+ tokensSkippedBySelection: z.number().default(0),
166
+ tokensInjected: z.number().default(0),
167
+ tokensTrimmedFromHistory: z.number().default(0),
168
+ tokensTrimmedCarlyBlocks: z.number().default(0),
169
+ totalTokensSaved: z.number().default(0),
170
+ })
171
+ .default({}),
172
+ sessions: z.array(CumulativeSessionSummarySchema).default([]),
173
+ });
174
+ // ---------------------------------------------------------------------------
175
+ // Session Override
176
+ // ---------------------------------------------------------------------------
177
+ export const SessionOverrideSchema = z.object({
178
+ /** Override DEVMODE for this session (null = inherit from manifest) */
179
+ devmode: z.boolean().nullable().default(null),
180
+ /** Per-domain state overrides (null = inherit from manifest) */
181
+ domainStates: z.record(z.string(), z.boolean().nullable()).default({}),
182
+ });
183
+ // ---------------------------------------------------------------------------
184
+ // Session Config (sessions/*.json)
185
+ // ---------------------------------------------------------------------------
186
+ export const SessionConfigSchema = z.object({
187
+ /** Session ID from OpenCode */
188
+ id: z.string(),
189
+ /** ISO timestamp when session was created */
190
+ started: z.string(),
191
+ /** Working directory for this session */
192
+ cwd: z.string(),
193
+ /** Short label derived from cwd (project directory name) */
194
+ label: z.string(),
195
+ /** User-editable session title (auto-generated from first prompt) */
196
+ title: z.string().nullable().default(null),
197
+ /** Number of prompts processed in this session */
198
+ promptCount: z.number().default(0),
199
+ /** ISO timestamp of last activity */
200
+ lastActivity: z.string(),
201
+ /** Files recently read or edited by tools in this session */
202
+ activeFiles: z.array(z.string()).default([]),
203
+ /** Session-specific overrides */
204
+ overrides: SessionOverrideSchema.default({}),
205
+ /** Cumulative token savings stats for this session */
206
+ tokenStats: TokenStatsSchema.default({}),
207
+ });
208
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * OpenCarly Context Bracket Resolution
3
+ *
4
+ * Maps prompt count to a context bracket (FRESH, MODERATE, DEPLETED, CRITICAL).
5
+ * Uses configurable thresholds from context.json.
6
+ */
7
+ import type { ContextFile, BracketName } from "../config/schema";
8
+ export interface BracketResult {
9
+ /** Current bracket name */
10
+ name: BracketName;
11
+ /** Rules for the current bracket */
12
+ rules: string[];
13
+ /** The threshold that was crossed (for display) */
14
+ threshold: number;
15
+ }
16
+ /**
17
+ * Determine the active context bracket based on prompt count.
18
+ *
19
+ * Brackets (from least to most urgent):
20
+ * - FRESH: promptCount < moderate threshold
21
+ * - MODERATE: promptCount >= moderate but < depleted
22
+ * - DEPLETED: promptCount >= depleted but < critical
23
+ * - CRITICAL: promptCount >= critical (uses DEPLETED rules + warning)
24
+ */
25
+ export declare function getBracket(promptCount: number, context: ContextFile): BracketResult;
26
+ //# sourceMappingURL=brackets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brackets.d.ts","sourceRoot":"","sources":["../../src/engine/brackets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAMjE,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,IAAI,EAAE,WAAW,CAAC;IAElB,oCAAoC;IACpC,KAAK,EAAE,MAAM,EAAE,CAAC;IAEhB,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,WAAW,GACnB,aAAa,CAiCf"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * OpenCarly Context Bracket Resolution
3
+ *
4
+ * Maps prompt count to a context bracket (FRESH, MODERATE, DEPLETED, CRITICAL).
5
+ * Uses configurable thresholds from context.json.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Bracket resolution
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Determine the active context bracket based on prompt count.
12
+ *
13
+ * Brackets (from least to most urgent):
14
+ * - FRESH: promptCount < moderate threshold
15
+ * - MODERATE: promptCount >= moderate but < depleted
16
+ * - DEPLETED: promptCount >= depleted but < critical
17
+ * - CRITICAL: promptCount >= critical (uses DEPLETED rules + warning)
18
+ */
19
+ export function getBracket(promptCount, context) {
20
+ const { thresholds, brackets } = context;
21
+ if (promptCount >= thresholds.critical) {
22
+ // CRITICAL uses depleted rules (same as CARL behavior)
23
+ return {
24
+ name: "CRITICAL",
25
+ rules: brackets.depleted.enabled ? brackets.depleted.rules : [],
26
+ threshold: thresholds.critical,
27
+ };
28
+ }
29
+ if (promptCount >= thresholds.depleted) {
30
+ return {
31
+ name: "DEPLETED",
32
+ rules: brackets.depleted.enabled ? brackets.depleted.rules : [],
33
+ threshold: thresholds.depleted,
34
+ };
35
+ }
36
+ if (promptCount >= thresholds.moderate) {
37
+ return {
38
+ name: "MODERATE",
39
+ rules: brackets.moderate.enabled ? brackets.moderate.rules : [],
40
+ threshold: thresholds.moderate,
41
+ };
42
+ }
43
+ return {
44
+ name: "FRESH",
45
+ rules: brackets.fresh.enabled ? brackets.fresh.rules : [],
46
+ threshold: 0,
47
+ };
48
+ }
49
+ //# sourceMappingURL=brackets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brackets.js","sourceRoot":"","sources":["../../src/engine/brackets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,WAAmB,EACnB,OAAoB;IAEpB,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEzC,IAAI,WAAW,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QACvC,uDAAuD;QACvD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YAC/D,SAAS,EAAE,UAAU,CAAC,QAAQ;SAC/B,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QACvC,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YAC/D,SAAS,EAAE,UAAU,CAAC,QAAQ;SAC/B,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QACvC,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YAC/D,SAAS,EAAE,UAAU,CAAC,QAAQ;SAC/B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACzD,SAAS,EAAE,CAAC;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Engine module exports
3
+ */
4
+ export { matchDomains, detectStarCommands, type MatchResult } from "./matcher";
5
+ export { loadRules, calculateBaseline, type LoadedRules } from "./loader";
6
+ export { getBracket, type BracketResult } from "./brackets";
7
+ export { trimMessageHistory, type TrimStats } from "./trimmer";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Engine module exports
3
+ */
4
+ export { matchDomains, detectStarCommands } from "./matcher";
5
+ export { loadRules, calculateBaseline } from "./loader";
6
+ export { getBracket } from "./brackets";
7
+ export { trimMessageHistory } from "./trimmer";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAoB,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAoB,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAsB,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAkB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * OpenCarly Rule Loader
3
+ *
4
+ * Loads rules from domain .md files, star-commands, and context brackets
5
+ * based on match results from the matcher.
6
+ */
7
+ import type { CarlyConfig } from "../config/manifest";
8
+ import type { MatchResult } from "./matcher";
9
+ import type { BracketResult } from "./brackets";
10
+ import type { BracketName } from "../config/schema";
11
+ export interface LoadedRules {
12
+ /** Always-on domain rules: { domainName: rules[] } */
13
+ alwaysOn: Record<string, string[]>;
14
+ /** Keyword-matched domain rules: { domainName: rules[] } */
15
+ matched: Record<string, string[]>;
16
+ /** Star-command rules: { commandName: rules[] } */
17
+ commands: Record<string, string[]>;
18
+ /** Context bracket rules for the current bracket */
19
+ bracketRules: string[];
20
+ /** Current context bracket name */
21
+ bracket: BracketName;
22
+ /** Prompt count info for display */
23
+ promptCount: number;
24
+ /** Bracket threshold for display */
25
+ bracketThreshold: number;
26
+ /** Keywords that triggered each matched domain */
27
+ matchedKeywords: Record<string, string[]>;
28
+ /** File paths that triggered each matched domain */
29
+ matchedPaths: Record<string, string[]>;
30
+ /** Domains excluded and why */
31
+ excludedDomains: Record<string, string[]>;
32
+ /** Global exclusion keywords found */
33
+ globalExcluded: string[];
34
+ /** Whether DEVMODE is active */
35
+ devmode: boolean;
36
+ /** Whether context bracket system is enabled */
37
+ contextEnabled: boolean;
38
+ /** Whether commands system is enabled */
39
+ commandsEnabled: boolean;
40
+ /** Domains that are available but not loaded (for summary) */
41
+ availableDomains: Array<{
42
+ name: string;
43
+ recall: string[];
44
+ }>;
45
+ /** Injection stats for DEVMODE display (populated by plugin entry point) */
46
+ injectionStats: {
47
+ rulesThisPrompt: number;
48
+ totalRulesSession: number;
49
+ totalPromptsSession: number;
50
+ avgRulesPerPrompt: number;
51
+ } | null;
52
+ /** Cumulative token savings for the session (populated by plugin entry point) */
53
+ tokenSavings: {
54
+ /** Tokens saved by not loading all rules every prompt */
55
+ skippedBySelection: number;
56
+ /** Tokens trimmed from conversation history (tool outputs) */
57
+ trimmedFromHistory: number;
58
+ /** Tokens trimmed from stale carly-rules blocks */
59
+ trimmedCarlyBlocks: number;
60
+ /** Total tokens of rules actually injected this session */
61
+ tokensInjected: number;
62
+ /** Baseline: what all rules would cost per prompt */
63
+ baselinePerPrompt: number;
64
+ /** Total estimated savings */
65
+ totalSaved: number;
66
+ /** Prompts processed */
67
+ promptsProcessed: number;
68
+ /** Whether *stats command is active (show full report) */
69
+ showFullReport: boolean;
70
+ } | null;
71
+ }
72
+ /**
73
+ * Calculate the "all rules loaded every prompt" baseline.
74
+ * This is what you'd get if you put everything in AGENTS.md.
75
+ * Returns estimated tokens per prompt.
76
+ */
77
+ export declare function calculateBaseline(config: CarlyConfig): number;
78
+ /**
79
+ * Load all rules based on match results, config, and current bracket.
80
+ */
81
+ export declare function loadRules(matchResult: MatchResult, config: CarlyConfig, bracket: BracketResult, promptCount: number): LoadedRules;
82
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/engine/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,kBAAkB,CAAC;AAMlE,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnC,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAElC,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnC,oDAAoD;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,mCAAmC;IACnC,OAAO,EAAE,WAAW,CAAC;IAErB,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IAEpB,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IAEzB,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAE1C,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvC,+BAA+B;IAC/B,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAE1C,sCAAsC;IACtC,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IAEjB,gDAAgD;IAChD,cAAc,EAAE,OAAO,CAAC;IAExB,yCAAyC;IACzC,eAAe,EAAE,OAAO,CAAC;IAEzB,8DAA8D;IAC9D,gBAAgB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAE5D,4EAA4E;IAC5E,cAAc,EAAE;QACd,eAAe,EAAE,MAAM,CAAC;QACxB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,iBAAiB,EAAE,MAAM,CAAC;KAC3B,GAAG,IAAI,CAAC;IAET,iFAAiF;IACjF,YAAY,EAAE;QACZ,yDAAyD;QACzD,kBAAkB,EAAE,MAAM,CAAC;QAC3B,8DAA8D;QAC9D,kBAAkB,EAAE,MAAM,CAAC;QAC3B,mDAAmD;QACnD,kBAAkB,EAAE,MAAM,CAAC;QAC3B,2DAA2D;QAC3D,cAAc,EAAE,MAAM,CAAC;QACvB,qDAAqD;QACrD,iBAAiB,EAAE,MAAM,CAAC;QAC1B,8BAA8B;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,wBAAwB;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,0DAA0D;QAC1D,cAAc,EAAE,OAAO,CAAC;KACzB,GAAG,IAAI,CAAC;CACV;AAsBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAgC7D;AAMD;;GAEG;AACH,wBAAgB,SAAS,CACvB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,MAAM,GAClB,WAAW,CAwFb"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * OpenCarly Rule Loader
3
+ *
4
+ * Loads rules from domain .md files, star-commands, and context brackets
5
+ * based on match results from the matcher.
6
+ */
7
+ import * as path from "path";
8
+ import { parseDomainFile } from "../config/manifest";
9
+ // ---------------------------------------------------------------------------
10
+ // Domain rule loading
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Load rules from a single domain's .md file.
14
+ */
15
+ function loadDomainRules(_domainName, domain, configPath) {
16
+ const filePath = path.join(configPath, domain.file);
17
+ return parseDomainFile(filePath);
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // Baseline calculation
21
+ // ---------------------------------------------------------------------------
22
+ /**
23
+ * Calculate the "all rules loaded every prompt" baseline.
24
+ * This is what you'd get if you put everything in AGENTS.md.
25
+ * Returns estimated tokens per prompt.
26
+ */
27
+ export function calculateBaseline(config) {
28
+ const { manifest, commands, configPath } = config;
29
+ let totalRuleText = 0;
30
+ // All domain rules
31
+ for (const [, domain] of Object.entries(manifest.domains)) {
32
+ if (domain.state === "inactive")
33
+ continue;
34
+ const filePath = path.join(configPath, domain.file);
35
+ const rules = parseDomainFile(filePath);
36
+ for (const rule of rules) {
37
+ totalRuleText += rule.length;
38
+ }
39
+ }
40
+ // All star-command rules
41
+ for (const [, cmd] of Object.entries(commands)) {
42
+ for (const rule of cmd.rules) {
43
+ totalRuleText += rule.length;
44
+ }
45
+ }
46
+ // All bracket rules
47
+ const { context } = config;
48
+ const bracketRuleLengths = [
49
+ context.brackets.fresh.rules.join("").length,
50
+ context.brackets.moderate.rules.join("").length,
51
+ context.brackets.depleted.rules.join("").length,
52
+ ];
53
+ totalRuleText += bracketRuleLengths.reduce((a, b) => a + b, 0);
54
+ // Convert chars to estimated tokens
55
+ return Math.ceil(totalRuleText / 4);
56
+ }
57
+ // ---------------------------------------------------------------------------
58
+ // Main loader
59
+ // ---------------------------------------------------------------------------
60
+ /**
61
+ * Load all rules based on match results, config, and current bracket.
62
+ */
63
+ export function loadRules(matchResult, config, bracket, promptCount) {
64
+ const { manifest, commands, configPath } = config;
65
+ const loaded = {
66
+ alwaysOn: {},
67
+ matched: {},
68
+ commands: {},
69
+ bracketRules: [],
70
+ bracket: bracket.name,
71
+ promptCount,
72
+ bracketThreshold: bracket.threshold,
73
+ matchedKeywords: matchResult.matched,
74
+ matchedPaths: matchResult.matchedPaths,
75
+ excludedDomains: matchResult.excluded,
76
+ globalExcluded: matchResult.globalExcluded,
77
+ devmode: manifest.devmode,
78
+ contextEnabled: manifest.context.state === "active",
79
+ commandsEnabled: manifest.commands.state === "active",
80
+ availableDomains: [],
81
+ injectionStats: null,
82
+ tokenSavings: null,
83
+ };
84
+ // Load always-on domain rules
85
+ for (const domainName of matchResult.alwaysOn) {
86
+ const domain = manifest.domains[domainName];
87
+ if (domain) {
88
+ const rules = loadDomainRules(domainName, domain, configPath);
89
+ if (rules.length > 0) {
90
+ loaded.alwaysOn[domainName] = rules;
91
+ }
92
+ }
93
+ }
94
+ // Load keyword-matched domain rules
95
+ for (const domainName of Object.keys(matchResult.matched)) {
96
+ const domain = manifest.domains[domainName];
97
+ if (domain) {
98
+ const rules = loadDomainRules(domainName, domain, configPath);
99
+ if (rules.length > 0) {
100
+ loaded.matched[domainName] = rules;
101
+ }
102
+ }
103
+ }
104
+ // Load path-matched domain rules
105
+ for (const domainName of Object.keys(matchResult.matchedPaths)) {
106
+ const domain = manifest.domains[domainName];
107
+ if (domain) {
108
+ const rules = loadDomainRules(domainName, domain, configPath);
109
+ if (rules.length > 0) {
110
+ // We put them in loaded.matched to be injected alongside keyword-matched rules
111
+ loaded.matched[domainName] = rules;
112
+ }
113
+ }
114
+ }
115
+ // Load star-command rules
116
+ if (manifest.commands.state === "active" && matchResult.starCommands.length > 0) {
117
+ for (const cmdName of matchResult.starCommands) {
118
+ const cmd = commands[cmdName];
119
+ if (cmd && cmd.rules.length > 0) {
120
+ loaded.commands[cmdName] = cmd.rules;
121
+ }
122
+ }
123
+ }
124
+ // Load context bracket rules
125
+ if (manifest.context.state === "active") {
126
+ loaded.bracketRules = bracket.rules;
127
+ }
128
+ // Collect available but not loaded domains (for summary)
129
+ for (const [name, domain] of Object.entries(manifest.domains)) {
130
+ if (domain.state === "inactive")
131
+ continue;
132
+ if (domain.alwaysOn)
133
+ continue;
134
+ // Skip if already matched or excluded
135
+ if (matchResult.matched[name])
136
+ continue;
137
+ if (matchResult.matchedPaths[name])
138
+ continue;
139
+ if (matchResult.excluded[name])
140
+ continue;
141
+ if (domain.recall.length > 0) {
142
+ loaded.availableDomains.push({ name, recall: domain.recall });
143
+ }
144
+ }
145
+ return loaded;
146
+ }
147
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/engine/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * OpenCarly Domain Matcher
3
+ *
4
+ * Scans user prompts for domain recall keywords and star-commands.
5
+ * Handles global and per-domain exclusions.
6
+ */
7
+ import type { Manifest } from "../config/schema";
8
+ export interface MatchResult {
9
+ /** Domains matched via recall keywords: { domainName: matchedKeywords[] } */
10
+ matched: Record<string, string[]>;
11
+ /** Domains matched via file paths: { domainName: matchedPaths[] } */
12
+ matchedPaths: Record<string, string[]>;
13
+ /** Domains excluded by per-domain exclusion: { domainName: excludingKeywords[] } */
14
+ excluded: Record<string, string[]>;
15
+ /** Global exclusion keywords that were found (blocks all matching) */
16
+ globalExcluded: string[];
17
+ /** Star-commands detected (lowercase, without asterisk) */
18
+ starCommands: string[];
19
+ /** Always-on domains that are active */
20
+ alwaysOn: string[];
21
+ }
22
+ /**
23
+ * Detect star-commands in the prompt.
24
+ * e.g. "*brief *dev explain this" -> ["brief", "dev"]
25
+ */
26
+ export declare function detectStarCommands(prompt: string): string[];
27
+ /**
28
+ * Check if a file path matches any of the given glob patterns.
29
+ */
30
+ export declare function isPathMatch(filePath: string, patterns: string[]): boolean;
31
+ /**
32
+ * Match domains against a user prompt.
33
+ *
34
+ * Algorithm:
35
+ * 1. Check globalExclude - if any match, skip all domain matching
36
+ * 2. Collect always-on active domains
37
+ * 3. For each active, non-alwaysOn domain:
38
+ * a. Check per-domain exclude keywords
39
+ * b. Check recall keywords
40
+ * 4. Detect star-commands
41
+ */
42
+ export declare function matchDomains(prompt: string, manifest: Manifest, activeFiles?: string[]): MatchResult;
43
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/engine/matcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMjD,MAAM,WAAW,WAAW;IAC1B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAElC,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvC,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEnC,sEAAsE;IACtE,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAU3D;AA0BD;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAOzE;AAsDD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,WAAW,GAAE,MAAM,EAAO,GACzB,WAAW,CA0Eb"}