@nexrall/code-core 1.4.74 → 1.4.76

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 CHANGED
@@ -12,6 +12,7 @@ npm install @nexrall/code-core
12
12
  |--------|-------------|
13
13
  | `@nexrall/code-core` | Everything via the root export |
14
14
  | `@nexrall/code-core/agent` | `runAgentLoop` — the main agentic loop |
15
+ | `@nexrall/code-core/agent-types` | `loadAgentTypes`, `findAgentType` — sub-agent type definitions |
15
16
  | `@nexrall/code-core/tools` | `executeTool` — built-in tool executor (bash, file I/O, search…) |
16
17
  | `@nexrall/code-core/symbols` | `getSymbols`, `getWorkspaceSymbols` — regex-based LSP-lite scanner |
17
18
  | `@nexrall/code-core/checkpoint` | `CheckpointManager` — persistent rewind / rollback |
@@ -33,7 +34,7 @@ const messages = [
33
34
  ];
34
35
 
35
36
  const opts: AgentLoopOptions = {
36
- model: 'turbo', // 'turbo' (Sonnet) | 'pro' (Opus) | 'ultra' (Fable 5)
37
+ model: 'claude-sonnet-5-5', // any catalogue model id; the tier aliases still work
37
38
  workDir: process.cwd(),
38
39
  env: { platform: 'node', cwd: process.cwd(), shell: 'bash' },
39
40
  clientType: 'cli',
@@ -53,13 +54,13 @@ const history = await runAgentLoop(messages, opts);
53
54
  console.log('Done —', history.length, 'messages');
54
55
  ```
55
56
 
56
- > **Requires authentication.** The agent streams through the Nexrall API — users must be logged in via `nexrall-code login` (or set `NEXRALL_TOKEN` env var).
57
+ > **Requires authentication.** The agent streams through the Nexrall API — users must be logged in via `nex auth` (or set the `NEXRALL_TOKEN` env var).
57
58
 
58
59
  ## Agent loop options
59
60
 
60
61
  ```ts
61
62
  interface AgentLoopOptions {
62
- model: 'turbo' | 'pro' | 'ultra';
63
+ model?: string; // e.g. 'claude-sonnet-5-5', 'gpt-6-astra', 'deepseek-flash'
63
64
  workDir: string;
64
65
  env: EnvContext;
65
66
  clientType?: 'cli' | 'vscode';
@@ -7,6 +7,16 @@ export interface AskOnceOptions {
7
7
  abortSignal?: {
8
8
  aborted: boolean;
9
9
  };
10
+ /**
11
+ * S20: the server-reported usage (and cost, when it sent one) of this call.
12
+ * Optional and additive — the auto-mode classifier uses it to enforce its
13
+ * per-session budget; every existing caller ignores it.
14
+ */
15
+ onUsage?: (u: {
16
+ input_tokens?: number;
17
+ output_tokens?: number;
18
+ cost?: number;
19
+ }) => void;
10
20
  }
11
21
  export declare function askModelOnce(prompt: string, opts: AskOnceOptions): Promise<string | null>;
12
22
  //# sourceMappingURL=askOnce.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"askOnce.d.ts","sourceRoot":"","sources":["../../src/agent/askOnce.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAgB,UAAU,EAAW,MAAM,UAAU,CAAC;AAKlE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACpC;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwC/F"}
1
+ {"version":3,"file":"askOnce.d.ts","sourceRoot":"","sources":["../../src/agent/askOnce.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAgB,UAAU,EAAW,MAAM,UAAU,CAAC;AAKlE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACzF;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgD/F"}
@@ -28,8 +28,16 @@ async function askModelOnce(prompt, opts) {
28
28
  env: opts.env ?? { cwd: opts.cwd },
29
29
  abortSignal: ctl,
30
30
  toolAllowlist: [NO_TOOLS_MARKER],
31
- }, () => {
32
- /* the final message carries the text */
31
+ }, (e) => {
32
+ // The final message carries the text; this tap only forwards usage.
33
+ if (opts.onUsage && e && e.type === 'usage') {
34
+ const ev = e;
35
+ opts.onUsage({
36
+ input_tokens: ev.usage?.input_tokens,
37
+ output_tokens: ev.usage?.output_tokens,
38
+ ...(typeof ev.cost === 'number' ? { cost: ev.cost } : {}),
39
+ });
40
+ }
33
41
  });
34
42
  const blocks = Array.isArray(msg.content) ? msg.content : [];
35
43
  const text = blocks
@@ -1 +1 @@
1
- {"version":3,"file":"planMode.d.ts","sourceRoot":"","sources":["../../src/agent/planMode.ts"],"names":[],"mappings":"AAwOA,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,EAAE,eAAe,GAAG,oBAAoB,CAAC;IAC/C,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;CACjB;AAuKD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CA8D1D;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAU3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,GAAG,IAAI,CAoClG;AAED,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,QAqBvB,CAAC"}
1
+ {"version":3,"file":"planMode.d.ts","sourceRoot":"","sources":["../../src/agent/planMode.ts"],"names":[],"mappings":"AAqPA,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,EAAE,eAAe,GAAG,oBAAoB,CAAC;IAC/C,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;CACjB;AAuKD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgE1D;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAU3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,GAAG,IAAI,CAoClG;AAED,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,QAqBvB,CAAC"}
@@ -163,6 +163,10 @@ const SYSTEM_BIN_DIRS = new Set(['/bin', '/usr/bin', '/usr/local/bin', '/sbin',
163
163
  */
164
164
  const UNSAFE_ENV = /^(PATH|HOME|SHELL|IFS|ENV|BASH_ENV|PAGER|MANPAGER|EDITOR|VISUAL|BROWSER|LD_\w*|DYLD_\w*|GIT_\w*|NODE_\w*|NPM_\w*|npm_\w*|PYTHON\w*|BASH\w*|RUBY\w*|PERL\w*|LESS\w*|XDG_\w*|\w*OPTS?)=/i;
165
165
  const GH_NOUNS = new Set(['pr', 'issue', 'run', 'repo', 'release', 'workflow', 'gist', 'label']);
166
+ /** glab's resource nouns — the guard against `glab api <verb>` (arbitrary HTTP), same as gh. */
167
+ const GLAB_NOUNS = new Set(['mr', 'issue', 'ci', 'repo', 'release', 'pipeline', 'job', 'variable', 'snippet']);
168
+ /** Which tools need a noun guard on their nested form (see the nested branch below). */
169
+ const NESTED_NOUNS = { gh: GH_NOUNS, glab: GLAB_NOUNS };
166
170
  /**
167
171
  * Subcommands that are read-only for tools whose safety depends on the verb.
168
172
  *
@@ -208,10 +212,17 @@ const READ_ONLY_SUBCOMMANDS = {
208
212
  // gh: read verbs only. `gh run rerun`, `gh pr merge` etc. are excluded, and
209
213
  // the nested-verb check in isReadOnlyCommand handles `gh pr view` vs `gh pr merge`.
210
214
  gh: new Set(['browse']),
215
+ // glab: everything read-only lives in the nested form (`glab mr view`), so the
216
+ // top-level set is empty and bare `glab` (help) is the only direct read.
217
+ glab: new Set([]),
211
218
  };
212
219
  /** Second-level read verbs for CLIs shaped as `<tool> <noun> <verb>`. */
213
220
  const READ_ONLY_NESTED = {
214
221
  gh: new Set(['view', 'list', 'status', 'diff', 'checks']),
222
+ // glab mirrors gh's readable set: `glab mr view/diff`, `glab ci status`. Writes
223
+ // (`glab mr note`, `merge`, `close`) are absent on purpose — S16b posts a review
224
+ // comment through the main agent, never through read-only classification.
225
+ glab: new Set(['view', 'list', 'diff', 'status']),
215
226
  };
216
227
  /**
217
228
  * Shell metacharacters that can smuggle a second command past verb inspection.
@@ -418,9 +429,11 @@ function isReadOnlyCommand(command) {
418
429
  if (subs.has(sub))
419
430
  return subcommandFlagsOk(verb, sub, words.slice(i + 1));
420
431
  const nested = READ_ONLY_NESTED[verb];
421
- // `gh api list -X DELETE` has "list" in second position too — the noun must be a
422
- // real resource noun, and `api` (arbitrary HTTP verbs) is not one.
423
- if (nested && rest[1] && nested.has(rest[1]) && (verb !== 'gh' || GH_NOUNS.has(sub)))
432
+ // `gh api list -X DELETE` (and `glab api done ...`) has "list"/"diff" in second
433
+ // position too — the noun must be a real resource noun; `api` (arbitrary HTTP
434
+ // verbs) is not one. Tools without a noun list behave as before.
435
+ const nouns = NESTED_NOUNS[verb];
436
+ if (nested && rest[1] && nested.has(rest[1]) && (!nouns || nouns.has(sub)))
424
437
  return true;
425
438
  return false;
426
439
  }
package/dist/index.d.ts CHANGED
@@ -32,10 +32,12 @@ export * from './permissions/rules';
32
32
  export * from './permissions/modePolicy';
33
33
  export * from './permissions/bashClassify';
34
34
  export * from './permissions/destructive';
35
+ export * from './permissions/autoMode';
35
36
  export * from './plugins/index';
36
37
  export * from './plugins/installer';
37
38
  export * from './plugins/sources';
38
39
  export * from './plugins/data';
40
+ export * from './plugins/eval';
39
41
  export * from './agent/trust';
40
42
  export * from './agent/crossProcessLock';
41
43
  export * from './agent/worktree';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -48,10 +48,12 @@ __exportStar(require("./permissions/rules"), exports);
48
48
  __exportStar(require("./permissions/modePolicy"), exports);
49
49
  __exportStar(require("./permissions/bashClassify"), exports);
50
50
  __exportStar(require("./permissions/destructive"), exports);
51
+ __exportStar(require("./permissions/autoMode"), exports);
51
52
  __exportStar(require("./plugins/index"), exports);
52
53
  __exportStar(require("./plugins/installer"), exports);
53
54
  __exportStar(require("./plugins/sources"), exports);
54
55
  __exportStar(require("./plugins/data"), exports);
56
+ __exportStar(require("./plugins/eval"), exports);
55
57
  __exportStar(require("./agent/trust"), exports);
56
58
  __exportStar(require("./agent/crossProcessLock"), exports);
57
59
  __exportStar(require("./agent/worktree"), exports);
@@ -0,0 +1,89 @@
1
+ export interface AutoModeLimitDef {
2
+ /** Short name shown by `nex auto-mode defaults` and in reports. */
3
+ label: string;
4
+ /** The prose the classifier reads. One sentence, concrete. */
5
+ text: string;
6
+ }
7
+ /**
8
+ * The built-in hard limits (CC's `$defaults` for `hard_deny`): unconditional —
9
+ * user intent does NOT clear these. Keep this list SHORT and beyond argument;
10
+ * it exists for the actions no request should ever authorize.
11
+ */
12
+ export declare const AUTO_MODE_HARD_DENY_DEFAULTS: readonly AutoModeLimitDef[];
13
+ /**
14
+ * The built-in soft limits (CC's `$defaults` for `soft_deny`): block UNLESS the
15
+ * user's own latest message directly and specifically asks for this exact
16
+ * action, or an allow exception matches.
17
+ */
18
+ export declare const AUTO_MODE_SOFT_DENY_DEFAULTS: readonly AutoModeLimitDef[];
19
+ /** The `$defaults` sentinel (CC's spelling) inside soft_deny / hard_deny lists. */
20
+ export declare const AUTO_MODE_DEFAULTS_SENTINEL = "$defaults";
21
+ export declare const AUTO_MODE_DEFAULT_MAX_CLASSIFICATIONS = 400;
22
+ export declare const AUTO_MODE_DEFAULT_MAX_BUDGET_USD = 0.25;
23
+ export interface AutoModeConfig {
24
+ /** Whether the classifier runs in auto mode at all. Default true. */
25
+ enabled: boolean;
26
+ /** Model for the review call; undefined = the session model. */
27
+ classifierModel?: string;
28
+ /** Prose: trusted infra (repos, buckets, domains, deploy targets). */
29
+ environment: string[];
30
+ /** Pre-approved patterns; clear soft blocks (never hard ones). */
31
+ allow: string[];
32
+ /** Effective soft limits (tier values + built-ins when $defaults applies). */
33
+ softDeny: string[];
34
+ /** Effective hard limits. */
35
+ hardDeny: string[];
36
+ /** Suspend EVERY bash allow rule while classifying (CC's flag). Default false. */
37
+ classifyAllShell: boolean;
38
+ maxClassifications: number;
39
+ maxBudgetUsd: number;
40
+ /** Which file (or '--settings') set which key — for `nex auto-mode config`. */
41
+ sources: Array<{
42
+ file: string;
43
+ keys: string[];
44
+ }>;
45
+ /** Project/local settings that tried to set `autoMode`; ignored for safety. */
46
+ ignoredProjectFiles: string[];
47
+ /** Non-fatal problems (bad types, unknown keys) — reported, never thrown. */
48
+ warnings: string[];
49
+ }
50
+ /**
51
+ * Load the effective auto-mode config.
52
+ *
53
+ * Tier order — LOW to HIGH precedence (a higher tier that defines a key wins
54
+ * WHOLESALE for that key): user < managed < session (`--settings`). Project and
55
+ * settings.local are read ONLY to report that their `autoMode` is ignored;
56
+ * they can never contribute a value. That asymmetry is the whole security
57
+ * model: settings travel with a checkout, and a checkout that could grant
58
+ * itself trust would make the classifier theatre.
59
+ */
60
+ export declare function loadAutoModeConfig(workDir: string): AutoModeConfig;
61
+ export interface ClassifyPromptInput {
62
+ tool: string;
63
+ input: Record<string, unknown>;
64
+ workDir: string;
65
+ /** Workspace extensions from --add-dir (trusted like the project). */
66
+ extraDirs?: string[];
67
+ /** Recent user messages, oldest → newest; the LAST is the current instruction. */
68
+ intent?: string[];
69
+ cfg: AutoModeConfig;
70
+ }
71
+ /**
72
+ * The review request. Deliberately one flat prompt — the classifier is a fresh,
73
+ * tool-less call (askModelOnce), so everything it may consult must be here:
74
+ * the limits, the environment, the action, and the human's actual words.
75
+ */
76
+ export declare function classifyPrompt(a: ClassifyPromptInput): string;
77
+ export type AutoModeVerdictAction = 'allow' | 'block-soft' | 'block-hard' | 'unavailable';
78
+ export interface AutoModeVerdict {
79
+ action: AutoModeVerdictAction;
80
+ reason?: string;
81
+ }
82
+ /** A local guard failed us (or the host never called in) — see the design doc. */
83
+ export declare const AUTO_MODE_UNAVAILABLE: AutoModeVerdict;
84
+ /**
85
+ * Parse one line of classifier output. Anything that is not a clear ALLOW is
86
+ * NOT an allow — a mangled or empty reply fails closed (`unavailable`).
87
+ */
88
+ export declare function parseClassifierReply(text: string | null | undefined): AutoModeVerdict;
89
+ //# sourceMappingURL=autoMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoMode.d.ts","sourceRoot":"","sources":["../../src/permissions/autoMode.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,SAAS,gBAAgB,EAmBnE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,SAAS,gBAAgB,EAiBnE,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,2BAA2B,cAAc,CAAC;AAEvD,eAAO,MAAM,qCAAqC,MAAM,CAAC;AACzD,eAAO,MAAM,gCAAgC,OAAO,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,kEAAkE;IAClE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACjD,+EAA+E;IAC/E,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAqFlE;AASD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,cAAc,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,mBAAmB,GAAG,MAAM,CA4C7D;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,aAAa,CAAC;AAE1F,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kFAAkF;AAClF,eAAO,MAAM,qBAAqB,EAAE,eAGnC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,CAcrF"}
@@ -0,0 +1,346 @@
1
+ "use strict";
2
+ // S20 — auto-mode config + the classifier's prompt/parse (see the design doc
3
+ // nexrall/docs/AUTO_MODE_CLASSIFIER.md).
4
+ //
5
+ // The pure half: where `autoMode` settings may come from (user + managed +
6
+ // --settings ONLY — never project/local, so a cloned repo cannot loosen the
7
+ // gate), how tiers merge, the built-in prose limits, the classifier prompt and
8
+ // the reply parser. The model CALL and the runtime (cache, budget, fast paths)
9
+ // live in the hosts — cli/src/permissions/autoClassify.ts for the CLI.
10
+ //
11
+ // The lists below are PROSE FOR A JUDGE, not regexes: they say what the
12
+ // classifier must protect, in the same words a human would, because the check
13
+ // is a model call and not another denylist (the destructive-token guard is
14
+ // that — and it stays the code-level floor, unchanged, underneath this).
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.AUTO_MODE_UNAVAILABLE = exports.AUTO_MODE_DEFAULT_MAX_BUDGET_USD = exports.AUTO_MODE_DEFAULT_MAX_CLASSIFICATIONS = exports.AUTO_MODE_DEFAULTS_SENTINEL = exports.AUTO_MODE_SOFT_DENY_DEFAULTS = exports.AUTO_MODE_HARD_DENY_DEFAULTS = void 0;
50
+ exports.loadAutoModeConfig = loadAutoModeConfig;
51
+ exports.classifyPrompt = classifyPrompt;
52
+ exports.parseClassifierReply = parseClassifierReply;
53
+ const fs = __importStar(require("fs"));
54
+ const path = __importStar(require("path"));
55
+ const os = __importStar(require("os"));
56
+ const rules_1 = require("./rules");
57
+ /**
58
+ * The built-in hard limits (CC's `$defaults` for `hard_deny`): unconditional —
59
+ * user intent does NOT clear these. Keep this list SHORT and beyond argument;
60
+ * it exists for the actions no request should ever authorize.
61
+ */
62
+ exports.AUTO_MODE_HARD_DENY_DEFAULTS = [
63
+ {
64
+ label: 'Data exfiltration',
65
+ text: 'Sending file contents, repository contents, environment variables, credentials or tokens to any network ' +
66
+ 'destination the user has not explicitly named (e.g. curl/wget with a body built from local files or env).',
67
+ },
68
+ {
69
+ label: 'Credential and system files',
70
+ text: 'Writing to or modifying security-sensitive locations outside the project: ~/.ssh, ~/.aws, ~/.config/gh, ' +
71
+ '~/.netrc, ~/.npmrc credential entries, shell rc files (.zshrc/.bashrc), /etc, or the OS keychain.',
72
+ },
73
+ {
74
+ label: 'Safety-system tampering',
75
+ text: "Disabling or weakening this session's own safety controls: editing permission rules or autoMode settings to " +
76
+ 'grant more access, clearing audit trails, or killing the permission gate.',
77
+ },
78
+ ];
79
+ /**
80
+ * The built-in soft limits (CC's `$defaults` for `soft_deny`): block UNLESS the
81
+ * user's own latest message directly and specifically asks for this exact
82
+ * action, or an allow exception matches.
83
+ */
84
+ exports.AUTO_MODE_SOFT_DENY_DEFAULTS = [
85
+ {
86
+ label: 'Git history rewrite',
87
+ text: 'Rewriting shared history: git push --force/--force-with-lease to a shared branch, or reset --hard that ' +
88
+ 'discards committed work.',
89
+ },
90
+ {
91
+ label: 'Database and infra destruction',
92
+ text: 'Destructive database or infrastructure operations against shared or production systems: DROP/DELETE/TRUNCATE ' +
93
+ 'on non-scratch data, terraform destroy, kubectl delete of shared resources, deleting cloud buckets.',
94
+ },
95
+ {
96
+ label: 'Mass deletion outside scratch space',
97
+ text: 'Deleting many files or whole directories outside the project workspace and scratch/temp locations.',
98
+ },
99
+ ];
100
+ /** The `$defaults` sentinel (CC's spelling) inside soft_deny / hard_deny lists. */
101
+ exports.AUTO_MODE_DEFAULTS_SENTINEL = '$defaults';
102
+ exports.AUTO_MODE_DEFAULT_MAX_CLASSIFICATIONS = 400;
103
+ exports.AUTO_MODE_DEFAULT_MAX_BUDGET_USD = 0.25;
104
+ function readTier(file) {
105
+ try {
106
+ const obj = JSON.parse(fs.readFileSync(file, 'utf-8'));
107
+ const am = obj?.autoMode;
108
+ return am && typeof am === 'object' && !Array.isArray(am) ? am : null;
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ /** Accept CC's snake_case spellings and our camelCase ones. */
115
+ function pickKey(am, ...names) {
116
+ for (const n of names) {
117
+ if (Object.prototype.hasOwnProperty.call(am, n))
118
+ return { key: n, value: am[n] };
119
+ }
120
+ return null;
121
+ }
122
+ function asProseList(value, key, warnings) {
123
+ if (!Array.isArray(value)) {
124
+ warnings.push(`autoMode.${key} must be an array of strings — ignored`);
125
+ return null;
126
+ }
127
+ return value
128
+ .filter((v) => typeof v === 'string')
129
+ .map((v) => v.trim())
130
+ .filter(Boolean);
131
+ }
132
+ function asBool(value, key, warnings) {
133
+ if (typeof value === 'boolean')
134
+ return value;
135
+ if (value === 'true')
136
+ return true;
137
+ if (value === 'false')
138
+ return false;
139
+ warnings.push(`autoMode.${key} must be true or false — ignored`);
140
+ return null;
141
+ }
142
+ function asPositiveNumber(value, key, warnings) {
143
+ const n = typeof value === 'number' ? value : Number(value);
144
+ if (!Number.isFinite(n) || n < 0) {
145
+ warnings.push(`autoMode.${key} must be a non-negative number — ignored`);
146
+ return null;
147
+ }
148
+ return n;
149
+ }
150
+ /** Expand `$defaults` in a list, or supply defaults when the key was never set. */
151
+ function expandDefaults(list, defaults) {
152
+ if (list === null)
153
+ return defaults.map((d) => `[${d.label}] ${d.text}`);
154
+ const out = [];
155
+ for (const item of list) {
156
+ if (item === exports.AUTO_MODE_DEFAULTS_SENTINEL)
157
+ out.push(...defaults.map((d) => `[${d.label}] ${d.text}`));
158
+ else
159
+ out.push(item);
160
+ }
161
+ return out;
162
+ }
163
+ /**
164
+ * Load the effective auto-mode config.
165
+ *
166
+ * Tier order — LOW to HIGH precedence (a higher tier that defines a key wins
167
+ * WHOLESALE for that key): user < managed < session (`--settings`). Project and
168
+ * settings.local are read ONLY to report that their `autoMode` is ignored;
169
+ * they can never contribute a value. That asymmetry is the whole security
170
+ * model: settings travel with a checkout, and a checkout that could grant
171
+ * itself trust would make the classifier theatre.
172
+ */
173
+ function loadAutoModeConfig(workDir) {
174
+ const warnings = [];
175
+ const sources = [];
176
+ const ignoredProjectFiles = [];
177
+ const userFile = path.join(os.homedir(), '.nexrall', 'settings.json');
178
+ const managedFile = (0, rules_1.managedSettingsPath)();
179
+ const tiers = [
180
+ { file: userFile, autoMode: readTier(userFile) },
181
+ { file: managedFile, autoMode: readTier(managedFile) },
182
+ { file: '--settings', autoMode: (0, rules_1.getSessionSettings)()?.autoMode ?? null },
183
+ ];
184
+ // A non-object there (e.g. the string "off") is still an attempt we must not
185
+ // swallow silently.
186
+ for (const cand of [
187
+ path.join(workDir, '.nexrall', 'settings.json'),
188
+ path.join(workDir, '.nexrall', 'settings.local.json'),
189
+ ]) {
190
+ try {
191
+ const obj = JSON.parse(fs.readFileSync(cand, 'utf-8'));
192
+ if (obj && Object.prototype.hasOwnProperty.call(obj, 'autoMode'))
193
+ ignoredProjectFiles.push(cand);
194
+ }
195
+ catch {
196
+ /* no file / unreadable — nothing ignored */
197
+ }
198
+ }
199
+ // Per-key merge, low → high.
200
+ let enabled = null;
201
+ let classifierModel;
202
+ let environment = null;
203
+ let allow = null;
204
+ let softList = null;
205
+ let hardList = null;
206
+ let classifyAllShell = null;
207
+ let maxClassifications = null;
208
+ let maxBudgetUsd = null;
209
+ for (const tier of tiers) {
210
+ if (!tier.autoMode)
211
+ continue;
212
+ const am = tier.autoMode;
213
+ const keys = [];
214
+ const take = (r, key) => {
215
+ if (r !== null && r !== undefined)
216
+ keys.push(key);
217
+ return r;
218
+ };
219
+ const en = pickKey(am, 'classifier', 'enabled');
220
+ if (en)
221
+ enabled = take(asBool(en.value, 'classifier', warnings) ?? enabled, en.key);
222
+ const cm = pickKey(am, 'classifierModel', 'classifier_model');
223
+ if (cm && typeof cm.value === 'string' && cm.value.trim()) {
224
+ classifierModel = cm.value.trim();
225
+ keys.push(cm.key);
226
+ }
227
+ const env = pickKey(am, 'environment');
228
+ if (env)
229
+ environment = take(asProseList(env.value, 'environment', warnings) ?? environment, 'environment');
230
+ const al = pickKey(am, 'allow');
231
+ if (al)
232
+ allow = take(asProseList(al.value, 'allow', warnings) ?? allow, 'allow');
233
+ const sd = pickKey(am, 'soft_deny', 'softDeny');
234
+ if (sd)
235
+ softList = take(asProseList(sd.value, sd.key, warnings) ?? softList, sd.key);
236
+ const hd = pickKey(am, 'hard_deny', 'hardDeny');
237
+ if (hd)
238
+ hardList = take(asProseList(hd.value, hd.key, warnings) ?? hardList, hd.key);
239
+ const ca = pickKey(am, 'classifyAllShell', 'classify_all_shell');
240
+ if (ca)
241
+ classifyAllShell = take(asBool(ca.value, ca.key, warnings) ?? classifyAllShell, ca.key);
242
+ const mc = pickKey(am, 'maxClassifications', 'max_classifications');
243
+ if (mc)
244
+ maxClassifications = take(asPositiveNumber(mc.value, mc.key, warnings) ?? maxClassifications, mc.key);
245
+ const mb = pickKey(am, 'maxBudgetUsd', 'max_budget_usd');
246
+ if (mb)
247
+ maxBudgetUsd = take(asPositiveNumber(mb.value, mb.key, warnings) ?? maxBudgetUsd, mb.key);
248
+ if (keys.length)
249
+ sources.push({ file: tier.file, keys });
250
+ }
251
+ return {
252
+ enabled: enabled ?? true,
253
+ ...(classifierModel ? { classifierModel } : {}),
254
+ environment: environment ?? [],
255
+ allow: allow ?? [],
256
+ softDeny: expandDefaults(softList, exports.AUTO_MODE_SOFT_DENY_DEFAULTS),
257
+ hardDeny: expandDefaults(hardList, exports.AUTO_MODE_HARD_DENY_DEFAULTS),
258
+ classifyAllShell: classifyAllShell ?? false,
259
+ maxClassifications: maxClassifications ?? exports.AUTO_MODE_DEFAULT_MAX_CLASSIFICATIONS,
260
+ maxBudgetUsd: maxBudgetUsd ?? exports.AUTO_MODE_DEFAULT_MAX_BUDGET_USD,
261
+ sources,
262
+ ignoredProjectFiles,
263
+ warnings,
264
+ };
265
+ }
266
+ // ─── The classifier's prompt + reply ─────────────────────────────────────────
267
+ /** Clip helper local to this module (the prompt must never grow unbounded). */
268
+ function clip(text, max) {
269
+ return text.length > max ? text.slice(0, max - 1) + '\u2026' : text;
270
+ }
271
+ /**
272
+ * The review request. Deliberately one flat prompt — the classifier is a fresh,
273
+ * tool-less call (askModelOnce), so everything it may consult must be here:
274
+ * the limits, the environment, the action, and the human's actual words.
275
+ */
276
+ function classifyPrompt(a) {
277
+ const list = (items) => (items.length ? items.map((t) => `- ${t}`).join('\n') : ' (none)');
278
+ const env = [
279
+ `The project directory ${a.workDir}${a.extraDirs?.length ? ` and the added directories ${a.extraDirs.join(', ')}` : ''}`,
280
+ "the current git repository's own configured remotes",
281
+ ...a.cfg.environment,
282
+ ];
283
+ const intent = a.intent?.length
284
+ ? a.intent.map((t, i) => `[${i + 1}] ${clip(t.replace(/\s+/g, ' ').trim(), 300)}`).join('\n')
285
+ : ' (none)';
286
+ let action;
287
+ try {
288
+ action = clip(JSON.stringify(a.input), 2000);
289
+ }
290
+ catch {
291
+ action = '(unserializable input)';
292
+ }
293
+ return ('You are the AUTO-MODE SAFETY CLASSIFIER for a coding agent.\n' +
294
+ 'The agent runs in "auto" mode: it will execute the action below WITHOUT asking the human, unless you block it.\n' +
295
+ "Judge the ACTION's real-world effect, not its wording.\n\n" +
296
+ 'HARD LIMITS — block unconditionally, even if the user asked:\n' +
297
+ list(a.cfg.hardDeny) +
298
+ "\n\nSOFT LIMITS — block UNLESS the user's latest message directly and specifically asks for this exact action, " +
299
+ 'or an ALLOW EXCEPTION matches:\n' +
300
+ list(a.cfg.softDeny) +
301
+ '\n\nALLOW EXCEPTIONS (pre-approved by the user; clear SOFT limits, never hard ones):\n' +
302
+ list(a.cfg.allow) +
303
+ '\n\nTRUSTED ENVIRONMENT (routine here; staying inside it is not a limit violation):\n' +
304
+ list(env) +
305
+ '\n\nTHE ACTION:\ntool: ' +
306
+ a.tool +
307
+ '\ninput: ' +
308
+ action +
309
+ '\n\nRECENT USER MESSAGES (intent; the LAST one is the current instruction):\n' +
310
+ intent +
311
+ '\n\nReply with EXACTLY ONE line, one of:\n' +
312
+ 'ALLOW\n' +
313
+ 'BLOCK: <one short reason>\n' +
314
+ 'BLOCK-HARD: <one short reason>\n' +
315
+ 'Use BLOCK only for a soft limit without clear user intent, BLOCK-HARD for a hard limit. ' +
316
+ 'For a routine, reversible action inside the workspace, reply ALLOW. No other text.');
317
+ }
318
+ /** A local guard failed us (or the host never called in) — see the design doc. */
319
+ exports.AUTO_MODE_UNAVAILABLE = {
320
+ action: 'unavailable',
321
+ reason: 'classifier could not review the action',
322
+ };
323
+ /**
324
+ * Parse one line of classifier output. Anything that is not a clear ALLOW is
325
+ * NOT an allow — a mangled or empty reply fails closed (`unavailable`).
326
+ */
327
+ function parseClassifierReply(text) {
328
+ if (typeof text !== 'string')
329
+ return { ...exports.AUTO_MODE_UNAVAILABLE, reason: 'no reply from the classifier' };
330
+ const first = text
331
+ .split('\n')
332
+ .find((l) => l.trim().length > 0)
333
+ ?.trim() ?? '';
334
+ if (!first)
335
+ return { ...exports.AUTO_MODE_UNAVAILABLE, reason: 'empty reply from the classifier' };
336
+ const hard = /^BLOCK[\s_-]*HARD\b[:\s-]*(.*)$/i.exec(first);
337
+ if (hard)
338
+ return { action: 'block-hard', reason: hard[1].trim() || 'hard limit' };
339
+ const soft = /^BLOCK\b[:\s-]*(.*)$/i.exec(first);
340
+ if (soft)
341
+ return { action: 'block-soft', reason: soft[1].trim() || 'soft limit' };
342
+ if (/^ALLOW\b/i.test(first))
343
+ return { action: 'allow' };
344
+ return { ...exports.AUTO_MODE_UNAVAILABLE, reason: `unrecognized classifier reply: ${clip(first, 80)}` };
345
+ }
346
+ //# sourceMappingURL=autoMode.js.map
@@ -9,11 +9,17 @@ export interface MergedSettings {
9
9
  /** Raw merged object (for hooks, allowedTools, etc.). */
10
10
  raw: Record<string, unknown>;
11
11
  }
12
+ export declare function managedSettingsPath(): string;
12
13
  /** Replace the rules supplied for this process by flags. Not persisted anywhere. */
13
14
  export declare function setSessionRules(r: Partial<PermissionRules>): void;
14
15
  export declare function setSessionSettings(obj: Record<string, unknown> | null): void;
15
16
  export declare function getSessionSettings(): Record<string, unknown> | null;
16
17
  export declare function loadSettings(workDir: string): MergedSettings;
18
+ /** The first ALLOW rule that matches this call, or null. S20's classifier gate
19
+ * reads this to tell a NARROW pre-approval (wins, no review) from a BROAD one
20
+ * (suspended while the classifier is on — see isBroadAllowRule). */
21
+ export declare function matchedAllowRule(rules: PermissionRules, tool: string, input: Record<string, unknown>, workDir: string): string | null;
22
+ export declare function isBroadAllowRule(rule: string): boolean;
17
23
  /**
18
24
  * Evaluate a tool call against merged rules. Returns the matching decision, or
19
25
  * null when no rule applies (caller decides the default, usually "ask").
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AA6BD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAEjE;AAQD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAE5E;AACD,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEnE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA8B5D;AAqJD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,MAAM,GACd,kBAAkB,GAAG,IAAI,CAK3B"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAQ5C;AAsBD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAEjE;AAQD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAE5E;AACD,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEnE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA8B5D;AAqJD;;oEAEoE;AACpE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAEf;AAYD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,MAAM,GACd,kBAAkB,GAAG,IAAI,CAK3B"}