indusagi-coding-agent 0.2.4 → 0.2.5
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/LICENSE +661 -0
- package/README.md +95 -1
- package/dist/entry.js +1559 -1100
- package/dist/guardrails.js +26 -509
- package/dist/index.js +1581 -1155
- package/package.json +8 -7
- package/dist/types/addons/addons.test.d.ts +0 -21
- package/dist/types/addons/contract.d.ts +0 -640
- package/dist/types/addons/dispatch/event-dispatcher.d.ts +0 -140
- package/dist/types/addons/dispatch/index.d.ts +0 -23
- package/dist/types/addons/dispatch/tool-interceptor.d.ts +0 -128
- package/dist/types/addons/host.d.ts +0 -246
- package/dist/types/addons/index.d.ts +0 -51
- package/dist/types/addons/manifest.d.ts +0 -56
- package/dist/types/addons/sandbox.d.ts +0 -103
- package/dist/types/addons/surface.d.ts +0 -42
- package/dist/types/boot/auth-vault.d.ts +0 -29
- package/dist/types/boot/boot.d.ts +0 -26
- package/dist/types/boot/boot.test.d.ts +0 -15
- package/dist/types/boot/contract.d.ts +0 -236
- package/dist/types/boot/heap.d.ts +0 -31
- package/dist/types/boot/index.d.ts +0 -20
- package/dist/types/boot/invocation.d.ts +0 -40
- package/dist/types/boot/invocation.test.d.ts +0 -8
- package/dist/types/boot/runners/addon-wiring.d.ts +0 -103
- package/dist/types/boot/runners/addon-wiring.test.d.ts +0 -19
- package/dist/types/boot/runners/checkpoint.d.ts +0 -133
- package/dist/types/boot/runners/checkpoint.test.d.ts +0 -12
- package/dist/types/boot/runners/delegate-runner.d.ts +0 -109
- package/dist/types/boot/runners/delegate-runner.test.d.ts +0 -13
- package/dist/types/boot/runners/index.d.ts +0 -13
- package/dist/types/boot/runners/link-runner.d.ts +0 -20
- package/dist/types/boot/runners/memdir.d.ts +0 -103
- package/dist/types/boot/runners/memdir.test.d.ts +0 -12
- package/dist/types/boot/runners/oneshot-runner.d.ts +0 -19
- package/dist/types/boot/runners/read-state.d.ts +0 -82
- package/dist/types/boot/runners/read-state.test.d.ts +0 -10
- package/dist/types/boot/runners/registry.d.ts +0 -30
- package/dist/types/boot/runners/repl-runner.d.ts +0 -19
- package/dist/types/boot/runners/server-mode.d.ts +0 -71
- package/dist/types/boot/runners/session-persist.test.d.ts +0 -10
- package/dist/types/boot/runners/session.d.ts +0 -88
- package/dist/types/boot/runners/session.test.d.ts +0 -15
- package/dist/types/boot/server-token.d.ts +0 -97
- package/dist/types/boot/stages.d.ts +0 -92
- package/dist/types/boot/upgrade/apply.d.ts +0 -45
- package/dist/types/boot/upgrade/index.d.ts +0 -13
- package/dist/types/boot/upgrade/upgrades.d.ts +0 -126
- package/dist/types/briefing/briefing.test.d.ts +0 -15
- package/dist/types/briefing/compose.d.ts +0 -37
- package/dist/types/briefing/context-docs.d.ts +0 -38
- package/dist/types/briefing/context-docs.test.d.ts +0 -18
- package/dist/types/briefing/contract.d.ts +0 -686
- package/dist/types/briefing/index.d.ts +0 -29
- package/dist/types/briefing/macros.d.ts +0 -206
- package/dist/types/briefing/skills.d.ts +0 -67
- package/dist/types/capability-deck/bridge-ledger/index.d.ts +0 -25
- package/dist/types/capability-deck/bridge-ledger/key.d.ts +0 -65
- package/dist/types/capability-deck/bridge-ledger/ledger.d.ts +0 -129
- package/dist/types/capability-deck/bridge-ledger/network.d.ts +0 -115
- package/dist/types/capability-deck/builtin-bridge.d.ts +0 -114
- package/dist/types/capability-deck/capability-deck.test.d.ts +0 -18
- package/dist/types/capability-deck/cards/bg-process-card.d.ts +0 -99
- package/dist/types/capability-deck/cards/index.d.ts +0 -37
- package/dist/types/capability-deck/cards/memory-card.d.ts +0 -68
- package/dist/types/capability-deck/cards/plan-file.d.ts +0 -56
- package/dist/types/capability-deck/cards/plan-tools.d.ts +0 -97
- package/dist/types/capability-deck/cards/plan-tools.test.d.ts +0 -9
- package/dist/types/capability-deck/cards/saas-card.d.ts +0 -78
- package/dist/types/capability-deck/cards/task-card.d.ts +0 -106
- package/dist/types/capability-deck/cards/todo-card.d.ts +0 -78
- package/dist/types/capability-deck/cards/workflow-card.d.ts +0 -55
- package/dist/types/capability-deck/cards/workflow-card.test.d.ts +0 -12
- package/dist/types/capability-deck/checkpoint.int.test.d.ts +0 -25
- package/dist/types/capability-deck/contract.d.ts +0 -318
- package/dist/types/capability-deck/index.d.ts +0 -46
- package/dist/types/capability-deck/manifest.d.ts +0 -60
- package/dist/types/capability-deck/provision.d.ts +0 -76
- package/dist/types/capability-deck/read-edit-gate.int.test.d.ts +0 -21
- package/dist/types/channels/channels.test.d.ts +0 -15
- package/dist/types/channels/contract.d.ts +0 -489
- package/dist/types/channels/framer.d.ts +0 -49
- package/dist/types/channels/index.d.ts +0 -24
- package/dist/types/channels/link/dialog.d.ts +0 -138
- package/dist/types/channels/link/driver.d.ts +0 -81
- package/dist/types/channels/link/index.d.ts +0 -13
- package/dist/types/channels/link/server.d.ts +0 -70
- package/dist/types/channels/oneshot.d.ts +0 -37
- package/dist/types/channels/ops.d.ts +0 -89
- package/dist/types/channels/session-ops.d.ts +0 -80
- package/dist/types/conductor/bash-guard.d.ts +0 -106
- package/dist/types/conductor/bash-guard.test.d.ts +0 -17
- package/dist/types/conductor/catalog/catalog.d.ts +0 -87
- package/dist/types/conductor/catalog/index.d.ts +0 -14
- package/dist/types/conductor/catalog/matcher.d.ts +0 -47
- package/dist/types/conductor/conductor.d.ts +0 -213
- package/dist/types/conductor/conductor.test.d.ts +0 -10
- package/dist/types/conductor/contract.d.ts +0 -838
- package/dist/types/conductor/diagnostics.d.ts +0 -183
- package/dist/types/conductor/diagnostics.test.d.ts +0 -10
- package/dist/types/conductor/index.d.ts +0 -26
- package/dist/types/conductor/permission-gate.integration.test.d.ts +0 -22
- package/dist/types/conductor/permission-wiring.test.d.ts +0 -14
- package/dist/types/conductor/permissions.d.ts +0 -287
- package/dist/types/conductor/permissions.test.d.ts +0 -12
- package/dist/types/conductor/plan-mode.integration.test.d.ts +0 -23
- package/dist/types/conductor/post-edit-diagnostics.test.d.ts +0 -18
- package/dist/types/conductor/quota-error.d.ts +0 -35
- package/dist/types/conductor/signal-hub/hub.d.ts +0 -83
- package/dist/types/conductor/signal-hub/index.d.ts +0 -19
- package/dist/types/conductor/signal-hub/translate.d.ts +0 -77
- package/dist/types/conductor/skill-parse/index.d.ts +0 -10
- package/dist/types/conductor/skill-parse/parse.d.ts +0 -67
- package/dist/types/conductor/submit.test.d.ts +0 -28
- package/dist/types/conductor/transcript-store/index.d.ts +0 -16
- package/dist/types/conductor/transcript-store/serialize.d.ts +0 -106
- package/dist/types/conductor/transcript-store/serialize.test.d.ts +0 -10
- package/dist/types/conductor/transcript-store/store.d.ts +0 -188
- package/dist/types/console/auth-status.d.ts +0 -28
- package/dist/types/console/components/AgentsView.d.ts +0 -41
- package/dist/types/console/components/BackgroundAgents.d.ts +0 -63
- package/dist/types/console/components/BackgroundAgents.test.d.ts +0 -8
- package/dist/types/console/components/Banner.d.ts +0 -110
- package/dist/types/console/components/Composer.d.ts +0 -37
- package/dist/types/console/components/StatusBar.d.ts +0 -42
- package/dist/types/console/components/TerminalConsole.d.ts +0 -27
- package/dist/types/console/components/WorkingIndicator.d.ts +0 -44
- package/dist/types/console/components/WorkingIndicator.test.d.ts +0 -9
- package/dist/types/console/components/banner-sweep.d.ts +0 -55
- package/dist/types/console/components/banner.test.d.ts +0 -9
- package/dist/types/console/components/welcome.d.ts +0 -115
- package/dist/types/console/components/welcome.test.d.ts +0 -9
- package/dist/types/console/console.test.d.ts +0 -19
- package/dist/types/console/contract.d.ts +0 -611
- package/dist/types/console/index.d.ts +0 -34
- package/dist/types/console/input/complete.d.ts +0 -120
- package/dist/types/console/input/dir-reader.d.ts +0 -28
- package/dist/types/console/input/index.d.ts +0 -24
- package/dist/types/console/input/input.test.d.ts +0 -14
- package/dist/types/console/input/keymap.d.ts +0 -193
- package/dist/types/console/input/paste.d.ts +0 -183
- package/dist/types/console/mount.d.ts +0 -53
- package/dist/types/console/overlays/approval-queue.d.ts +0 -88
- package/dist/types/console/overlays/approval.d.ts +0 -104
- package/dist/types/console/overlays/approval.test.d.ts +0 -17
- package/dist/types/console/overlays/auth.d.ts +0 -31
- package/dist/types/console/overlays/boards.d.ts +0 -55
- package/dist/types/console/overlays/host.d.ts +0 -45
- package/dist/types/console/overlays/index.d.ts +0 -15
- package/dist/types/console/overlays/pickers.d.ts +0 -37
- package/dist/types/console/overlays/sessions.d.ts +0 -29
- package/dist/types/console/reducer.d.ts +0 -51
- package/dist/types/console/slash/builtins.d.ts +0 -33
- package/dist/types/console/slash/commands/dynamic.d.ts +0 -57
- package/dist/types/console/slash/commands/dynamic.test.d.ts +0 -9
- package/dist/types/console/slash/commands/integrations.d.ts +0 -28
- package/dist/types/console/slash/commands/integrations.test.d.ts +0 -18
- package/dist/types/console/slash/commands/shared.d.ts +0 -72
- package/dist/types/console/slash/commands/transcript.d.ts +0 -24
- package/dist/types/console/slash/commands/transcript.test.d.ts +0 -10
- package/dist/types/console/slash/commands/workbench.d.ts +0 -21
- package/dist/types/console/slash/commands/workbench.test.d.ts +0 -10
- package/dist/types/console/slash/index.d.ts +0 -34
- package/dist/types/console/slash/registry.d.ts +0 -90
- package/dist/types/console/slash/resolve.d.ts +0 -109
- package/dist/types/console/slash/slash.test.d.ts +0 -18
- package/dist/types/console/startup.d.ts +0 -119
- package/dist/types/console/theme/adapter.d.ts +0 -79
- package/dist/types/console/theme/index.d.ts +0 -18
- package/dist/types/console/theme/palette.d.ts +0 -77
- package/dist/types/console/theme/resolve.d.ts +0 -45
- package/dist/types/console/theme/theme.test.d.ts +0 -16
- package/dist/types/console/theme/tokens.d.ts +0 -62
- package/dist/types/entry.d.ts +0 -17
- package/dist/types/guardrails.d.ts +0 -33
- package/dist/types/index.d.ts +0 -24
- package/dist/types/insight/channel.d.ts +0 -45
- package/dist/types/insight/contract.d.ts +0 -411
- package/dist/types/insight/index.d.ts +0 -26
- package/dist/types/insight/insight.test.d.ts +0 -17
- package/dist/types/insight/recorder.d.ts +0 -63
- package/dist/types/insight/redaction.d.ts +0 -44
- package/dist/types/insight/replay.d.ts +0 -77
- package/dist/types/insight/sampling.d.ts +0 -84
- package/dist/types/insight/serialize.d.ts +0 -54
- package/dist/types/insight/sinks/console.d.ts +0 -36
- package/dist/types/insight/sinks/file.d.ts +0 -37
- package/dist/types/insight/sinks/index.d.ts +0 -16
- package/dist/types/insight/sinks/stream.d.ts +0 -53
- package/dist/types/kit/clipboard-image.d.ts +0 -40
- package/dist/types/kit/external-editor.d.ts +0 -35
- package/dist/types/kit/image.d.ts +0 -102
- package/dist/types/kit/index.d.ts +0 -29
- package/dist/types/kit/kit.test.d.ts +0 -13
- package/dist/types/kit/shell.d.ts +0 -50
- package/dist/types/kit/tool-fetch.d.ts +0 -165
- package/dist/types/launch/catalog.d.ts +0 -51
- package/dist/types/launch/contract.d.ts +0 -387
- package/dist/types/launch/credentials.d.ts +0 -112
- package/dist/types/launch/index.d.ts +0 -28
- package/dist/types/launch/invocation/attachments.d.ts +0 -72
- package/dist/types/launch/invocation/flags.d.ts +0 -59
- package/dist/types/launch/invocation/index.d.ts +0 -23
- package/dist/types/launch/invocation/read.d.ts +0 -52
- package/dist/types/launch/invocation/usage.d.ts +0 -25
- package/dist/types/launch/launch.test.d.ts +0 -20
- package/dist/types/launch/login.d.ts +0 -68
- package/dist/types/launch/oauth.d.ts +0 -101
- package/dist/types/launch/oauth.test.d.ts +0 -20
- package/dist/types/launch/packages.d.ts +0 -75
- package/dist/types/launch/packages.test.d.ts +0 -15
- package/dist/types/launch/pickers.d.ts +0 -97
- package/dist/types/runtime-bridge/bridges/_drive.d.ts +0 -74
- package/dist/types/runtime-bridge/bridges/builtins.d.ts +0 -77
- package/dist/types/runtime-bridge/bridges/claude-cli.d.ts +0 -37
- package/dist/types/runtime-bridge/bridges/codex-cli.d.ts +0 -27
- package/dist/types/runtime-bridge/bridges/index.d.ts +0 -15
- package/dist/types/runtime-bridge/bridges/indusagi-cli.d.ts +0 -36
- package/dist/types/runtime-bridge/broker.d.ts +0 -182
- package/dist/types/runtime-bridge/contract.d.ts +0 -436
- package/dist/types/runtime-bridge/index.d.ts +0 -21
- package/dist/types/runtime-bridge/runtime-bridge.test.d.ts +0 -17
- package/dist/types/runtime-bridge/sink.d.ts +0 -59
- package/dist/types/sessions/contract.d.ts +0 -79
- package/dist/types/sessions/index.d.ts +0 -11
- package/dist/types/sessions/library.d.ts +0 -95
- package/dist/types/sessions/sessions.test.d.ts +0 -11
- package/dist/types/settings/contract.d.ts +0 -175
- package/dist/types/settings/index.d.ts +0 -13
- package/dist/types/settings/manager.d.ts +0 -109
- package/dist/types/settings/settings.test.d.ts +0 -16
- package/dist/types/transcript-export/index.d.ts +0 -20
- package/dist/types/transcript-export/publish.d.ts +0 -81
- package/dist/types/transcript-export/sgr.d.ts +0 -90
- package/dist/types/transcript-export/template.d.ts +0 -64
- package/dist/types/transcript-export/theme-bridge.d.ts +0 -99
- package/dist/types/transcript-export/transcript-export.test.d.ts +0 -16
- package/dist/types/window-budget/budget/estimate.d.ts +0 -47
- package/dist/types/window-budget/budget/gate.d.ts +0 -37
- package/dist/types/window-budget/budget/index.d.ts +0 -14
- package/dist/types/window-budget/budget/slice.d.ts +0 -38
- package/dist/types/window-budget/condenser.d.ts +0 -73
- package/dist/types/window-budget/contract.d.ts +0 -182
- package/dist/types/window-budget/index.d.ts +0 -17
- package/dist/types/window-budget/microcompact.d.ts +0 -68
- package/dist/types/window-budget/microcompact.test.d.ts +0 -16
- package/dist/types/window-budget/rehydrate.d.ts +0 -56
- package/dist/types/window-budget/summarize/condense.d.ts +0 -76
- package/dist/types/window-budget/summarize/index.d.ts +0 -12
- package/dist/types/window-budget/summarize/prompt.d.ts +0 -56
- package/dist/types/window-budget/window-budget.test.d.ts +0 -18
- package/dist/types/workflow-engine/agent-runner.d.ts +0 -124
- package/dist/types/workflow-engine/agent-runner.test.d.ts +0 -8
- package/dist/types/workflow-engine/display.d.ts +0 -148
- package/dist/types/workflow-engine/display.test.d.ts +0 -1
- package/dist/types/workflow-engine/engine.d.ts +0 -183
- package/dist/types/workflow-engine/engine.test.d.ts +0 -1
- package/dist/types/workflow-engine/index.d.ts +0 -21
- package/dist/types/workflow-engine/parse.d.ts +0 -64
- package/dist/types/workflow-engine/parse.test.d.ts +0 -1
- package/dist/types/workflow-engine/structured-output.d.ts +0 -51
- package/dist/types/workflow-engine/structured-output.test.d.ts +0 -1
- package/dist/types/workspace/brand.d.ts +0 -26
- package/dist/types/workspace/index.d.ts +0 -11
- package/dist/types/workspace/locator.d.ts +0 -50
- package/dist/types/workspace/runtime-detect.d.ts +0 -56
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Post-edit live diagnostics — an LSP-free, shell-sourced baseline-diff engine.
|
|
3
|
-
*
|
|
4
|
-
* The full induscode story runs a long-lived LSP and pulls structured
|
|
5
|
-
* diagnostics off the language server. That stack is out of scope for the
|
|
6
|
-
* clean-room product, so this is the **pragmatic shell path**: after a turn that
|
|
7
|
-
* edited TypeScript/JS files, the conductor asks this engine to run a project
|
|
8
|
-
* checker (`tsc --noEmit`, plus `eslint --format json` when an eslint config is
|
|
9
|
-
* present), scoped to the workspace, and diff the result against a *per-session
|
|
10
|
-
* baseline* captured before the edits. Only the diagnostics that are genuinely
|
|
11
|
-
* **new** (not in the baseline, not already delivered in a prior turn) are
|
|
12
|
-
* surfaced, and they are injected into the NEXT agent turn as a follow-up note.
|
|
13
|
-
*
|
|
14
|
-
* Everything here is best-effort and non-fatal:
|
|
15
|
-
* - the checker spawns its OWN child process (lazy `node:child_process`), so
|
|
16
|
-
* the module stays importable in a non-Node test context;
|
|
17
|
-
* - a missing/slow/erroring checker NEVER faults the turn — the run is bounded
|
|
18
|
-
* by an {@link AbortController} timeout and every failure resolves to `[]`;
|
|
19
|
-
* - results are deduplicated and volume-capped (10/file, 30 total,
|
|
20
|
-
* severity-sorted) so a broken project can't dump hundreds of lines into
|
|
21
|
-
* context;
|
|
22
|
-
* - it is fully opt-out-able (`DiagnosticsConfig.enabled === false`) and
|
|
23
|
-
* defaults OFF when the workspace has no `tsconfig.json`.
|
|
24
|
-
*
|
|
25
|
-
* The line/column convention mirrors the LSP `Diagnostic.range`: 0-based.
|
|
26
|
-
* `tsc` reports 1-based positions, so {@link runTscDiagnostics} subtracts 1 and
|
|
27
|
-
* {@link formatDiagnosticsSummary} re-adds 1 when rendering for a human/agent.
|
|
28
|
-
*/
|
|
29
|
-
/** Severity rank, ordered most→least urgent for the volume cap's sort. */
|
|
30
|
-
export type DiagnosticSeverity = "Error" | "Warning" | "Info" | "Hint";
|
|
31
|
-
/** A zero-based line/column position. */
|
|
32
|
-
export interface Position {
|
|
33
|
-
readonly line: number;
|
|
34
|
-
readonly character: number;
|
|
35
|
-
}
|
|
36
|
-
/** A single diagnostic, shaped after the LSP `Diagnostic` (0-based range). */
|
|
37
|
-
export interface Diagnostic {
|
|
38
|
-
readonly message: string;
|
|
39
|
-
readonly severity: DiagnosticSeverity;
|
|
40
|
-
readonly range: {
|
|
41
|
-
readonly start: Position;
|
|
42
|
-
readonly end: Position;
|
|
43
|
-
};
|
|
44
|
-
readonly source?: string;
|
|
45
|
-
readonly code?: string | number;
|
|
46
|
-
}
|
|
47
|
-
/** All diagnostics for one file, keyed by an absolute fs path used as the uri. */
|
|
48
|
-
export interface DiagnosticFile {
|
|
49
|
-
readonly uri: string;
|
|
50
|
-
readonly diagnostics: Diagnostic[];
|
|
51
|
-
}
|
|
52
|
-
/** Max diagnostics surfaced for any single file (mirrors the LSP registry cap). */
|
|
53
|
-
export declare const MAX_PER_FILE = 10;
|
|
54
|
-
/** Max diagnostics surfaced across all files in one turn. */
|
|
55
|
-
export declare const MAX_TOTAL = 30;
|
|
56
|
-
/** Char budget for the rendered summary (truncated past this). */
|
|
57
|
-
export declare const MAX_SUMMARY_CHARS = 4000;
|
|
58
|
-
/**
|
|
59
|
-
* A stable identity for one diagnostic: position + code + (trimmed) message.
|
|
60
|
-
* Two diagnostics with the same key are "the same problem" for dedup/baseline
|
|
61
|
-
* purposes even across separate checker runs.
|
|
62
|
-
*/
|
|
63
|
-
export declare function createDiagnosticKey(d: Diagnostic): string;
|
|
64
|
-
/** Structural equality over a diagnostic's salient fields (via the dedup key). */
|
|
65
|
-
export declare function areDiagnosticsEqual(a: Diagnostic, b: Diagnostic): boolean;
|
|
66
|
-
/** Options for {@link deduplicateAndCap}. */
|
|
67
|
-
export interface DedupOptions {
|
|
68
|
-
readonly maxPerFile?: number;
|
|
69
|
-
readonly maxTotal?: number;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Filter, deduplicate, severity-sort, and volume-cap a batch of diagnostic
|
|
73
|
-
* files against a cross-turn `delivered` ledger.
|
|
74
|
-
*
|
|
75
|
-
* - drops any diagnostic whose key is already in `delivered[uri]` (already
|
|
76
|
-
* surfaced in a prior turn — don't nag);
|
|
77
|
-
* - dedups within a file (identical keys collapse to one);
|
|
78
|
-
* - sorts each file's diagnostics by severity then position;
|
|
79
|
-
* - caps to `maxPerFile` per file and `maxTotal` overall (errors win the cap);
|
|
80
|
-
* - records every diagnostic it RETURNS into `delivered` (FIFO-capped per uri)
|
|
81
|
-
* so the next turn won't re-surface it.
|
|
82
|
-
*
|
|
83
|
-
* `delivered` is mutated in place. Files that end up empty are dropped.
|
|
84
|
-
*/
|
|
85
|
-
export declare function deduplicateAndCap(files: readonly DiagnosticFile[], delivered: Map<string, Set<string>>, opts?: DedupOptions): DiagnosticFile[];
|
|
86
|
-
/** Inline ASCII severity marker (no `figures` dep). */
|
|
87
|
-
export declare function getSeveritySymbol(severity: DiagnosticSeverity): string;
|
|
88
|
-
/**
|
|
89
|
-
* Render a deduped/capped batch into a compact, agent-readable block. Positions
|
|
90
|
-
* are re-converted to 1-based for display (the engine carries 0-based). The
|
|
91
|
-
* output is truncated to `maxChars` so it can never blow up a context window.
|
|
92
|
-
*/
|
|
93
|
-
export declare function formatDiagnosticsSummary(files: readonly DiagnosticFile[], maxChars?: number): string;
|
|
94
|
-
/** A diagnostics source: produces files for the workspace, honoring `signal`. */
|
|
95
|
-
export type DiagnosticRunner = (cwd: string, signal?: AbortSignal) => Promise<DiagnosticFile[]>;
|
|
96
|
-
/**
|
|
97
|
-
* Run a project `tsc --noEmit --pretty false` and parse the flat diagnostic
|
|
98
|
-
* lines. Resolves to `[]` on ANY failure (binary missing, abort, non-Node).
|
|
99
|
-
* The local `node_modules/.bin/tsc` is preferred over a global/`npx` install to
|
|
100
|
-
* avoid a version mismatch with the project's own config.
|
|
101
|
-
*
|
|
102
|
-
* tsc lines look like: `src/x.ts(12,5): error TS2322: Type 'a' ...`
|
|
103
|
-
* Positions are 1-based in tsc; we store them 0-based (subtract 1).
|
|
104
|
-
*/
|
|
105
|
-
export declare function runTscDiagnostics(cwd: string, signal?: AbortSignal): Promise<DiagnosticFile[]>;
|
|
106
|
-
/** Parse the combined stdout/stderr of a `tsc --pretty false` run. */
|
|
107
|
-
export declare function parseTscOutput(output: string, cwd: string): DiagnosticFile[];
|
|
108
|
-
/**
|
|
109
|
-
* Run a project `eslint --format json` over `files` and parse the result.
|
|
110
|
-
* Resolves to `[]` when eslint is absent, no config is found, or anything else
|
|
111
|
-
* goes wrong. severity 2→Error, 1→Warning. Positions are 1-based; stored 0-based.
|
|
112
|
-
*/
|
|
113
|
-
export declare function runEslintDiagnostics(files: readonly string[], cwd: string, signal?: AbortSignal): Promise<DiagnosticFile[]>;
|
|
114
|
-
/** Parse `eslint --format json` output. Resolves config-not-found to `[]`. */
|
|
115
|
-
export declare function parseEslintOutput(output: string, cwd: string): DiagnosticFile[];
|
|
116
|
-
/** Configuration for the {@link DiagnosticsEngine}. */
|
|
117
|
-
export interface DiagnosticsConfig {
|
|
118
|
-
/** Master switch. When `false` the engine reports nothing (opt-out). */
|
|
119
|
-
readonly enabled?: boolean;
|
|
120
|
-
/** The diagnostic sources to run. Defaults to `[runTscDiagnostics]`. */
|
|
121
|
-
readonly runners?: DiagnosticRunner[];
|
|
122
|
-
/** Per-run timeout in ms before the checker is aborted (default 30000). */
|
|
123
|
-
readonly timeoutMs?: number;
|
|
124
|
-
/** Per-file cap (default {@link MAX_PER_FILE}). */
|
|
125
|
-
readonly maxPerFile?: number;
|
|
126
|
-
/** Total cap (default {@link MAX_TOTAL}). */
|
|
127
|
-
readonly maxTotal?: number;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* The post-edit diagnostics engine: runs checkers, diffs against a per-session
|
|
131
|
-
* baseline, and dedups across turns. Stateful and per-session — one instance
|
|
132
|
-
* lives on the conductor for the life of a session.
|
|
133
|
-
*/
|
|
134
|
-
export declare class DiagnosticsEngine {
|
|
135
|
-
#private;
|
|
136
|
-
constructor(cwd: string, config?: DiagnosticsConfig);
|
|
137
|
-
/** Whether this engine is active. */
|
|
138
|
-
get enabled(): boolean;
|
|
139
|
-
/** Whether the per-session baseline has already been captured. */
|
|
140
|
-
get hasBaseline(): boolean;
|
|
141
|
-
/**
|
|
142
|
-
* Capture the per-session baseline NOW (before any edits land) by running the
|
|
143
|
-
* checkers once over the current project state. Every diagnostic present is
|
|
144
|
-
* recorded as pre-existing, so a later {@link newDiagnostics} surfaces only the
|
|
145
|
-
* problems the session's own edits introduced. Idempotent: a second call is a
|
|
146
|
-
* no-op once a baseline exists. Best-effort — never throws.
|
|
147
|
-
*
|
|
148
|
-
* Prefer calling this at session start (before the agent can edit anything); if
|
|
149
|
-
* it is never called, {@link newDiagnostics} falls back to seeding the baseline
|
|
150
|
-
* on its first invocation.
|
|
151
|
-
*/
|
|
152
|
-
seedBaseline(signal?: AbortSignal): Promise<void>;
|
|
153
|
-
/**
|
|
154
|
-
* Run every checker, restrict the results to `editedPaths`, subtract the
|
|
155
|
-
* per-session baseline, dedup against prior turns, and volume-cap. Returns the
|
|
156
|
-
* NEW diagnostics for the edited files (empty when nothing new). Best-effort:
|
|
157
|
-
* never throws, never blocks beyond the configured timeout.
|
|
158
|
-
*
|
|
159
|
-
* The first invocation seeds the baseline from the current project state and
|
|
160
|
-
* returns `[]` (the pre-existing problems are the baseline, not "new").
|
|
161
|
-
*/
|
|
162
|
-
newDiagnostics(editedPaths: readonly string[], signal?: AbortSignal): Promise<DiagnosticFile[]>;
|
|
163
|
-
/**
|
|
164
|
-
* Forget the delivered-key history for one uri so a problem at that file can
|
|
165
|
-
* re-surface (e.g. the agent edited it again). The baseline is left intact.
|
|
166
|
-
*/
|
|
167
|
-
clearDeliveredForFile(uri: string): void;
|
|
168
|
-
/** Drop all cross-turn state and the baseline (re-seeds on the next run). */
|
|
169
|
-
reset(): void;
|
|
170
|
-
}
|
|
171
|
-
/** Whether a path looks like a TypeScript/JS source file (by extension). */
|
|
172
|
-
export declare function isTypeScriptOrJs(filePath: string): boolean;
|
|
173
|
-
/**
|
|
174
|
-
* Whether the workspace has a `tsconfig.json` at its root — the signal used to
|
|
175
|
-
* default the engine ON. Best-effort + synchronous: a probe failure (or a
|
|
176
|
-
* non-Node context) reports `false` so the engine defaults OFF and stays inert.
|
|
177
|
-
*/
|
|
178
|
-
export declare function hasTsConfig(cwd: string): boolean;
|
|
179
|
-
/**
|
|
180
|
-
* Whether the workspace has an eslint config at its root — the signal used to
|
|
181
|
-
* additionally enable the eslint runner. Best-effort + synchronous.
|
|
182
|
-
*/
|
|
183
|
-
export declare function hasEslintConfig(cwd: string): boolean;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for the LSP-free post-edit diagnostics engine: the pure keying /
|
|
3
|
-
* dedup / cap / render logic, the tsc + eslint output parsers, and the
|
|
4
|
-
* baseline-diff behavior of {@link DiagnosticsEngine}.
|
|
5
|
-
*
|
|
6
|
-
* No network and no real `tsc`/`eslint` spawn — the engine is driven with
|
|
7
|
-
* scripted in-memory runners so the baseline/diff/dedup logic is exercised
|
|
8
|
-
* deterministically.
|
|
9
|
-
*/
|
|
10
|
-
export {};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conductor subsystem — public barrel.
|
|
3
|
-
*
|
|
4
|
-
* Re-exports the FROZEN Phase-2 contract: the product-level signal stream
|
|
5
|
-
* ({@link SessionSignal}), the typed fault model ({@link ConductorFault} +
|
|
6
|
-
* {@link conductorFault}), the on-disk transcript schema ({@link TranscriptEntry},
|
|
7
|
-
* {@link SessionHead}, {@link TRANSCRIPT_SCHEMA}), the model catalog/matcher
|
|
8
|
-
* reference types ({@link ModelCardRef}, {@link MatchQuery}), the immutable
|
|
9
|
-
* state snapshot ({@link ConductorState}), and the {@link SessionConductor}
|
|
10
|
-
* interface plus its {@link SessionConductorOptions}.
|
|
11
|
-
*
|
|
12
|
-
* Behavior modules (signal hub, transcript store, model catalog/matcher,
|
|
13
|
-
* conductor factory, the conductor itself) are added to this barrel as they
|
|
14
|
-
* land; consumers import the conductor surface from `src/conductor` rather than
|
|
15
|
-
* reaching into individual modules.
|
|
16
|
-
*/
|
|
17
|
-
export type { FaultKind, ConductorFault, SessionSignal, SignalKind, SignalOf, SignalHandler, TranscriptSchema, TranscriptRole, TranscriptEntry, SessionHead, ModelCardRef, MatchQuery, ConductorPhase, ConductorState, QueueMode, QueuedInput, SessionStats, ExecuteBashOptions, BashOutcome, SessionConductor, SessionConductorOptions, CondenseOutcome, AgentMessage, AgentTool, CanUseToolFn, ThinkingLevel, Model, Usage, KnownProvider, PermissionMode, } from "./contract";
|
|
18
|
-
export { conductorFault, TRANSCRIPT_SCHEMA } from "./contract";
|
|
19
|
-
export { createSessionConductor, reduceState, noopCondense, withGatewayBaseUrl, type AgentLike, type ConductorDeps, type CondenseFn, type RetryPolicy, } from "./conductor";
|
|
20
|
-
export { SignalHub, translateAgentEvent, type SignalHubOptions } from "./signal-hub";
|
|
21
|
-
export { ModelCatalog, ModelMatcher, canonicalId, toCardRef, type CatalogCard, type CatalogSource, type ResolveInput, } from "./catalog";
|
|
22
|
-
export { TranscriptStore, memoryBackend, fsBackend, replay, type TranscriptBackend, type TranscriptState, type TranscriptClock, type TranscriptStoreOptions, } from "./transcript-store";
|
|
23
|
-
export { parseSkillInvocation, type SkillInvocation } from "./skill-parse";
|
|
24
|
-
export { resolveRuleDecision, parseRule, makeRule, toolMatchesRule, createPermissionGate, createSubagentPermissionGate, collectReadOnlyToolNames, allowAlwaysRuleStrings, isReadOnlyToolName, isEditToolName, READ_ONLY_TOOL_NAMES, EDIT_TOOL_NAMES, type PermissionBehavior, type PermissionRule, type PermissionDecision, type CanUseToolFn as PermissionCanUseToolFn, type ApprovalChoice, type ApprovalOutcome, type ApprovalResolver, type PermissionGateConfig, type SessionPermissionPolicy, } from "./permissions";
|
|
25
|
-
export { parseBashCommand, catastrophicReason, isCatastrophicCommand, evaluateCatastrophic, bashSubcommandSubjects, type ParsedCommand, } from "./bash-guard";
|
|
26
|
-
export { DiagnosticsEngine, createDiagnosticKey, deduplicateAndCap, formatDiagnosticsSummary, getSeveritySymbol, parseTscOutput, parseEslintOutput, runTscDiagnostics, runEslintDiagnostics, hasTsConfig, hasEslintConfig, isTypeScriptOrJs, areDiagnosticsEqual, MAX_PER_FILE, MAX_TOTAL, MAX_SUMMARY_CHARS, type Diagnostic, type DiagnosticFile, type DiagnosticSeverity, type DiagnosticsConfig, type DiagnosticRunner, type DedupOptions, type Position, } from "./diagnostics";
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permission gate — integration against the REAL wired framework loop.
|
|
3
|
-
*
|
|
4
|
-
* The point of this suite (vs the pure {@link "./permissions.test"} unit tests) is
|
|
5
|
-
* to prove the gate actually lands where tools execute. It drives a real
|
|
6
|
-
* `indusagi/agent` `Agent` — the exact class the conductor's `makeAgent` wires —
|
|
7
|
-
* with a scripted `streamFn` that has the model request a tool call, and the
|
|
8
|
-
* SAME `createPermissionGate` output the conductor threads in as `canUseTool`.
|
|
9
|
-
*
|
|
10
|
-
* We assert through the framework's own message list (not a mock of an unwired
|
|
11
|
-
* module):
|
|
12
|
-
* - a **deny** rule blocks the tool: it never executes, and the turn carries an
|
|
13
|
-
* `isError` tool result with the deny message (an unanswered tool_use would
|
|
14
|
-
* 400 the next call, so the loop must still emit the result);
|
|
15
|
-
* - an **allow** rule (or read-only auto-allow) lets the tool execute;
|
|
16
|
-
* - **acceptEdits** auto-allows an edit without a rule;
|
|
17
|
-
* - **bypass** allows everything;
|
|
18
|
-
* - **plan** denies a mutating tool;
|
|
19
|
-
* - an **ask** with no host resolver denies (non-interactive default);
|
|
20
|
-
* - a live **mode switch** retargets subsequent calls with no agent rebuild.
|
|
21
|
-
*/
|
|
22
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conductor permission wiring — proves `createSessionConductor` threads the gate
|
|
3
|
-
* factory and exposes live `permissionMode()` / `setPermissionMode()`.
|
|
4
|
-
*
|
|
5
|
-
* The end-to-end "gate blocks a real tool" proof lives in
|
|
6
|
-
* {@link "./permission-gate.integration.test"} (it drives the real framework
|
|
7
|
-
* loop). Here we pin the PRODUCT seam: the conductor (a) seeds the mode from
|
|
8
|
-
* options, (b) updates it through `setPermissionMode`, and (c) hands the gate
|
|
9
|
-
* factory a getter that reads the conductor's LIVE mode — so a mode switch after
|
|
10
|
-
* assembly is visible to the gate with no agent rebuild. A scripted fake
|
|
11
|
-
* `AgentLike` keeps it network/disk-free, and a separate check confirms the gate
|
|
12
|
-
* factory IS resolved with a live-mode getter on the real-agent path.
|
|
13
|
-
*/
|
|
14
|
-
export {};
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permission rule engine + the `canUseTool` gate seam.
|
|
3
|
-
*
|
|
4
|
-
* This module is the product-side brain of the permission stack. It is split in
|
|
5
|
-
* two layers:
|
|
6
|
-
*
|
|
7
|
-
* 1. **A pure rule engine** — {@link resolveRuleDecision} maps a single tool
|
|
8
|
-
* call `(toolName, input, mode, rules)` to a {@link PermissionBehavior}
|
|
9
|
-
* (`allow` / `ask` / `deny`). It is total, synchronous, and side-effect free
|
|
10
|
-
* so the precedence (deny > ask > mode auto-allow > allow) is exhaustively
|
|
11
|
-
* unit-testable. Rule strings are induscode-style: a bare tool name
|
|
12
|
-
* (`"Bash"`) or a tool name with an argument specifier
|
|
13
|
-
* (`"Bash(npm run test:*)"`).
|
|
14
|
-
*
|
|
15
|
-
* 2. **A gate factory** — {@link createPermissionGate} turns that engine into a
|
|
16
|
-
* framework {@link CanUseToolFn}: the hard async hook the framework agent
|
|
17
|
-
* awaits immediately before every tool runs. An `ask` decision is routed to
|
|
18
|
-
* an OPTIONAL host-supplied approval resolver; when the resolver is absent
|
|
19
|
-
* (a non-interactive boot) `ask` denies with a clear message. An
|
|
20
|
-
* `allow-always` approval appends a session-scoped allow rule so later
|
|
21
|
-
* identical calls auto-allow.
|
|
22
|
-
*
|
|
23
|
-
* Backwards-compatibility: the framework `canUseTool` hook is itself optional, so
|
|
24
|
-
* a session that never builds a gate keeps today's allow-all behavior. A gate
|
|
25
|
-
* built from an empty rule set in `default` mode allows read-only tools and asks
|
|
26
|
-
* for everything else — and, with no resolver, the `ask` denials are explicit
|
|
27
|
-
* rather than silent.
|
|
28
|
-
*/
|
|
29
|
-
import type { PermissionMode } from "../settings";
|
|
30
|
-
/** Re-exported so consumers of the engine get the mode vocabulary in one import. */
|
|
31
|
-
export type { PermissionMode };
|
|
32
|
-
/** The verdict the rule engine renders for a single tool call. */
|
|
33
|
-
export type PermissionBehavior = "allow" | "ask" | "deny";
|
|
34
|
-
/**
|
|
35
|
-
* One parsed permission rule: a behavior plus the tool it targets, with an
|
|
36
|
-
* optional argument specifier (`ruleContent`) that further narrows the match.
|
|
37
|
-
*/
|
|
38
|
-
export interface PermissionRule {
|
|
39
|
-
/** What happens when this rule matches a tool call. */
|
|
40
|
-
readonly ruleBehavior: PermissionBehavior;
|
|
41
|
-
/** The tool (and optional argument specifier) this rule selects. */
|
|
42
|
-
readonly ruleValue: {
|
|
43
|
-
/** The canonical tool name, e.g. `"Bash"` / `"bash"` (matched case-insensitively). */
|
|
44
|
-
readonly toolName: string;
|
|
45
|
-
/** An optional argument specifier, e.g. `"npm run test:*"`. Absent = bare match. */
|
|
46
|
-
readonly ruleContent?: string;
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* The framework's tool-permission verdict. Mirrors `indusagi/agent`'s
|
|
51
|
-
* `PermissionDecision`; re-declared here so the product engine never imports the
|
|
52
|
-
* framework just for a structural type (the gate is assignable to the
|
|
53
|
-
* framework's `CanUseToolFn` because the shapes coincide).
|
|
54
|
-
*/
|
|
55
|
-
export type PermissionDecision = {
|
|
56
|
-
behavior: "allow";
|
|
57
|
-
updatedInput?: unknown;
|
|
58
|
-
} | {
|
|
59
|
-
behavior: "deny";
|
|
60
|
-
message: string;
|
|
61
|
-
};
|
|
62
|
-
/**
|
|
63
|
-
* The hard permission gate the framework agent awaits before each tool executes.
|
|
64
|
-
* Structurally identical to `indusagi/agent`'s `CanUseToolFn`, so a value of this
|
|
65
|
-
* type is accepted by `new Agent({ canUseTool })` with no cast.
|
|
66
|
-
*/
|
|
67
|
-
export type CanUseToolFn = (toolName: string, input: unknown, opts: {
|
|
68
|
-
signal?: AbortSignal;
|
|
69
|
-
}) => Promise<PermissionDecision>;
|
|
70
|
-
/**
|
|
71
|
-
* The outcome of the host approval prompt raised for an `ask` decision:
|
|
72
|
-
* - `allow-once` — run this single call, do not remember.
|
|
73
|
-
* - `allow-always` — run it and append a session allow rule for the tool.
|
|
74
|
-
* - `deny` — block this call.
|
|
75
|
-
*/
|
|
76
|
-
export type ApprovalChoice = "allow-once" | "allow-always" | "deny";
|
|
77
|
-
/**
|
|
78
|
-
* What an {@link ApprovalResolver} may resolve to: a user's {@link ApprovalChoice},
|
|
79
|
-
* or `"unavailable"` — the conductor's stable delegate answers that when NO
|
|
80
|
-
* interactive resolver is installed behind it (a headless boot, or the console not
|
|
81
|
-
* yet mounted). The gate maps `"unavailable"` to the actionable "requires
|
|
82
|
-
* approval" deny (pointing at `--permission-mode` / settings allow rules) rather
|
|
83
|
-
* than the "denied by the user" message, which would be false when no user ever
|
|
84
|
-
* saw a prompt.
|
|
85
|
-
*/
|
|
86
|
-
export type ApprovalOutcome = ApprovalChoice | "unavailable";
|
|
87
|
-
/**
|
|
88
|
-
* The OPTIONAL host approval resolver. When present, an `ask` decision awaits it;
|
|
89
|
-
* the host (an interactive overlay) returns the user's choice. It MUST resolve to
|
|
90
|
-
* `"deny"` on abort so a cancelled turn never hangs on a pending prompt. When the
|
|
91
|
-
* resolver is absent (non-interactive boot / oneshot / link), an `ask` decision
|
|
92
|
-
* deterministically denies. A stable pass-through delegate (the conductor's)
|
|
93
|
-
* resolves `"unavailable"` while no real resolver is installed behind it, so the
|
|
94
|
-
* gate can surface the actionable non-interactive deny message instead of a
|
|
95
|
-
* fictitious user denial.
|
|
96
|
-
*/
|
|
97
|
-
export type ApprovalResolver = (toolName: string, input: unknown, opts: {
|
|
98
|
-
signal?: AbortSignal;
|
|
99
|
-
}) => Promise<ApprovalOutcome>;
|
|
100
|
-
/**
|
|
101
|
-
* Tool names known to only inspect state (never mutate). Mirrors the framework's
|
|
102
|
-
* `READ_ONLY_TOOL_NAMES`; matched case-insensitively. A tool the framework marks
|
|
103
|
-
* `readOnly: true` is also auto-allowed via {@link createPermissionGate}'s
|
|
104
|
-
* `readOnlyToolNames` option, so this set is the static fallback for callers that
|
|
105
|
-
* only know names.
|
|
106
|
-
*/
|
|
107
|
-
export declare const READ_ONLY_TOOL_NAMES: ReadonlySet<string>;
|
|
108
|
-
/**
|
|
109
|
-
* Tool names that mutate the workspace by editing or writing files. Auto-allowed
|
|
110
|
-
* under `acceptEdits`, and (together with every other non-read-only tool) denied
|
|
111
|
-
* under `plan`.
|
|
112
|
-
*/
|
|
113
|
-
export declare const EDIT_TOOL_NAMES: ReadonlySet<string>;
|
|
114
|
-
/** Whether `toolName` is a statically-known read-only tool. */
|
|
115
|
-
export declare function isReadOnlyToolName(toolName: string, extra?: ReadonlySet<string>): boolean;
|
|
116
|
-
/** Whether `toolName` is an edit/write tool (auto-allowed under `acceptEdits`). */
|
|
117
|
-
export declare function isEditToolName(toolName: string): boolean;
|
|
118
|
-
/**
|
|
119
|
-
* Parse an induscode-style rule string into its tool name and optional argument
|
|
120
|
-
* specifier.
|
|
121
|
-
*
|
|
122
|
-
* - `"Bash"` → `{ toolName: "Bash" }`
|
|
123
|
-
* - `"Bash(npm run test:*)"` → `{ toolName: "Bash", ruleContent: "npm run test:*" }`
|
|
124
|
-
* - `"mcp__server"` → `{ toolName: "mcp__server" }`
|
|
125
|
-
*
|
|
126
|
-
* Whitespace around the tool name is trimmed; an empty argument specifier
|
|
127
|
-
* (`"Bash()"`) is treated as a bare rule.
|
|
128
|
-
*/
|
|
129
|
-
export declare function parseRule(raw: string): {
|
|
130
|
-
toolName: string;
|
|
131
|
-
ruleContent?: string;
|
|
132
|
-
};
|
|
133
|
-
/**
|
|
134
|
-
* Build a {@link PermissionRule} from a behavior and an induscode-style rule
|
|
135
|
-
* string. The single place a raw settings list entry becomes a typed rule.
|
|
136
|
-
*/
|
|
137
|
-
export declare function makeRule(ruleBehavior: PermissionBehavior, raw: string): PermissionRule;
|
|
138
|
-
/**
|
|
139
|
-
* Whether a tool call matches a rule (the ANY-match semantics used for deny/ask).
|
|
140
|
-
*
|
|
141
|
-
* The tool name must match (case-insensitive), with an `mcp__server` rule also
|
|
142
|
-
* matching every `mcp__server__tool` under it (the induscode MCP-wildcard
|
|
143
|
-
* convention). A bare rule (no specifier) matches any arguments.
|
|
144
|
-
*
|
|
145
|
-
* When the rule carries an argument specifier:
|
|
146
|
-
* - for the **shell** tool the command is split into its constituent
|
|
147
|
-
* sub-commands and the specifier is tested against EACH — a match on ANY
|
|
148
|
-
* sub-command counts (so `Bash(rm:*)` denies `git status && rm x`);
|
|
149
|
-
* - for any other tool the specifier is tested against the single rendered
|
|
150
|
-
* subject (the command field, or a JSON encoding).
|
|
151
|
-
*
|
|
152
|
-
* The any-match semantics are correct for `deny` and `ask` (a single offending
|
|
153
|
-
* sub-command should trigger them). The `allow` branch needs ALL sub-commands
|
|
154
|
-
* covered instead — see {@link bashAllowCoversAll}.
|
|
155
|
-
*/
|
|
156
|
-
export declare function toolMatchesRule(toolName: string, input: unknown, rule: PermissionRule): boolean;
|
|
157
|
-
/**
|
|
158
|
-
* Resolve the behavior for a single tool call against the rule set and mode.
|
|
159
|
-
*
|
|
160
|
-
* Precedence, highest first:
|
|
161
|
-
* 1. **deny rules** — any matching `deny` rule blocks, regardless of mode. Deny
|
|
162
|
-
* wins across every tier (the caller concatenates the tiers before passing
|
|
163
|
-
* the list in, and this scans all deny rules first).
|
|
164
|
-
* 2. **plan mode** — denies any mutating (non-read-only) tool outright.
|
|
165
|
-
* 3. **ask rules** — a matching `ask` rule forces a prompt (unless a deny
|
|
166
|
-
* already fired). Mode auto-allow does NOT override an explicit ask.
|
|
167
|
-
* 4. **bypass mode** — allows everything not already denied/asked.
|
|
168
|
-
* 5. **read-only auto-allow** — a known read-only tool allows in any mode.
|
|
169
|
-
* 6. **acceptEdits mode** — auto-allows edit/write tools.
|
|
170
|
-
* 7. **allow rules** — a matching `allow` rule (or, for the shell tool, the
|
|
171
|
-
* allow rule SET) allows.
|
|
172
|
-
* 8. **fallthrough** — `ask` (the safe default: prompt, then deny when no
|
|
173
|
-
* resolver is wired).
|
|
174
|
-
*
|
|
175
|
-
* The catastrophic-command blocklist sits ABOVE all of this (step 0): a shell
|
|
176
|
-
* command on the built-in blocklist (`rm -rf /`, fork bombs, `curl | sh`, …) is
|
|
177
|
-
* denied regardless of rules or mode — even `bypass` cannot run it. See
|
|
178
|
-
* {@link evaluateCatastrophic}.
|
|
179
|
-
*
|
|
180
|
-
* Shell handling threads through the per-sub-command matching: a compound
|
|
181
|
-
* command (`a && b; c | d`) is split into its constituent commands and each rule
|
|
182
|
-
* is evaluated against each — a deny/ask on ANY sub-command fires, while
|
|
183
|
-
* auto-allow requires the allow rule set to cover EVERY sub-command.
|
|
184
|
-
*
|
|
185
|
-
* Pure and total: no I/O, no async, deterministic for a given input.
|
|
186
|
-
*/
|
|
187
|
-
export declare function resolveRuleDecision(toolName: string, input: unknown, rules: readonly PermissionRule[], mode: PermissionMode, readOnlyExtra?: ReadonlySet<string>): PermissionBehavior;
|
|
188
|
-
/**
|
|
189
|
-
* The rule strings an `allow-always` approval mints — i.e. what the session will
|
|
190
|
-
* REMEMBER for this tool call.
|
|
191
|
-
*
|
|
192
|
-
* For the shell tool the remembered rules are scoped to the command: one
|
|
193
|
-
* `Bash(<sub-command>)` rule per constituent sub-command (so approving
|
|
194
|
-
* `git status && npm test` remembers both halves, and re-running either — or the
|
|
195
|
-
* same compound — auto-allows), but approving one command never whitelists the
|
|
196
|
-
* whole shell. Every other tool remembers the bare tool name (`Edit`), matching
|
|
197
|
-
* the prompt's "remember the tool for this session" copy.
|
|
198
|
-
*
|
|
199
|
-
* Exported so the approval overlay can show the user exactly what "Allow always"
|
|
200
|
-
* will remember (the `suggestions` line), and so the gate and the UI can never
|
|
201
|
-
* disagree about it.
|
|
202
|
-
*/
|
|
203
|
-
export declare function allowAlwaysRuleStrings(toolName: string, input: unknown): string[];
|
|
204
|
-
/** Configuration for {@link createPermissionGate}. */
|
|
205
|
-
export interface PermissionGateConfig {
|
|
206
|
-
/**
|
|
207
|
-
* The ordered rule set, already concatenated across the project/global tiers.
|
|
208
|
-
* Deny rules are scanned first so a deny anywhere in the list wins.
|
|
209
|
-
*/
|
|
210
|
-
readonly rules: readonly PermissionRule[];
|
|
211
|
-
/** A live getter for the current permission mode (so a mode switch is honored). */
|
|
212
|
-
readonly mode: () => PermissionMode;
|
|
213
|
-
/**
|
|
214
|
-
* The OPTIONAL host approval resolver consulted on an `ask` decision. Absent on
|
|
215
|
-
* a non-interactive boot — then `ask` deterministically denies.
|
|
216
|
-
*/
|
|
217
|
-
readonly requestApproval?: ApprovalResolver;
|
|
218
|
-
/**
|
|
219
|
-
* Append a session-scoped allow rule when the host returns `allow-always`. The
|
|
220
|
-
* boot layer owns the mutable rule list (the SAME array instance `rules` refers
|
|
221
|
-
* to) and passes a push here, so the appended rule is visible to every
|
|
222
|
-
* subsequent gate consultation within the session — and to every other gate
|
|
223
|
-
* built over the same list (sub-agent gates included). Session-scoped only:
|
|
224
|
-
* the rule is never persisted to settings.
|
|
225
|
-
*/
|
|
226
|
-
readonly appendAllowRule?: (rule: PermissionRule) => void;
|
|
227
|
-
/**
|
|
228
|
-
* Tool names (beyond {@link READ_ONLY_TOOL_NAMES}) to treat as read-only —
|
|
229
|
-
* derived from the deck's `readOnly: true` tool flags so MCP/custom read-only
|
|
230
|
-
* tools also auto-allow.
|
|
231
|
-
*/
|
|
232
|
-
readonly readOnlyToolNames?: ReadonlySet<string>;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Build a framework {@link CanUseToolFn} from the rule engine + the current mode.
|
|
236
|
-
*
|
|
237
|
-
* The returned gate:
|
|
238
|
-
* - resolves the behavior via {@link resolveRuleDecision},
|
|
239
|
-
* - on `allow` proceeds (the framework keeps the validated args),
|
|
240
|
-
* - on `deny` short-circuits with a clear message (the framework turns it into
|
|
241
|
-
* an `isError` tool result so the model sees why),
|
|
242
|
-
* - on `ask` awaits {@link PermissionGateConfig.requestApproval} when present —
|
|
243
|
-
* `allow-once` proceeds, `allow-always` proceeds and appends a session allow
|
|
244
|
-
* rule, `deny` blocks — and DENIES when no resolver is wired (the safe
|
|
245
|
-
* non-interactive default).
|
|
246
|
-
*
|
|
247
|
-
* The result is assignable to `indusagi/agent`'s `CanUseToolFn`.
|
|
248
|
-
*/
|
|
249
|
-
export declare function createPermissionGate(config: PermissionGateConfig): CanUseToolFn;
|
|
250
|
-
/**
|
|
251
|
-
* The live permission policy a session shares with its sub-agent runners (the
|
|
252
|
-
* `task` and `workflow` tools): the SAME mutable rule list the parent gate reads
|
|
253
|
-
* — so a session-scoped `allow-always` rule and the settings deny/ask rules are
|
|
254
|
-
* enforced inside delegations too — plus a live getter onto the parent
|
|
255
|
-
* conductor's permission mode, so a mid-run Shift+Tab (bypass → default, plan,
|
|
256
|
-
* back to bypass, …) retargets the very next sub-agent tool call.
|
|
257
|
-
*/
|
|
258
|
-
export interface SessionPermissionPolicy {
|
|
259
|
-
/** The session's ordered rule list — the live array, never a snapshot. */
|
|
260
|
-
readonly rules: readonly PermissionRule[];
|
|
261
|
-
/** Live getter onto the parent session's current permission mode. */
|
|
262
|
-
readonly mode: () => PermissionMode;
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Collect the names of every tool flagged `readOnly: true` (structurally probed,
|
|
266
|
-
* so any deck/framework/MCP tool shape works). These names are auto-allowed by
|
|
267
|
-
* the gate in `default`/`acceptEdits`/`plan` beyond the static
|
|
268
|
-
* {@link READ_ONLY_TOOL_NAMES}.
|
|
269
|
-
*/
|
|
270
|
-
export declare function collectReadOnlyToolNames(tools: ReadonlyArray<{
|
|
271
|
-
readonly name: string;
|
|
272
|
-
}>): ReadonlySet<string>;
|
|
273
|
-
/**
|
|
274
|
-
* Build the RESOLVER-LESS gate a sub-agent runs under.
|
|
275
|
-
*
|
|
276
|
-
* A sub-agent cannot prompt the user, so no {@link ApprovalResolver} is wired:
|
|
277
|
-
* an `ask` decision deterministically denies with an actionable message, while
|
|
278
|
-
* deny rules, plan-mode enforcement, the catastrophic-bash blocklist, read-only
|
|
279
|
-
* auto-allow, and bypass/acceptEdits behaviour all apply per inner tool call —
|
|
280
|
-
* against the LIVE parent mode, so mid-run mode switches reach delegations too.
|
|
281
|
-
*
|
|
282
|
-
* @param policy the session's shared rules + live mode getter
|
|
283
|
-
* @param tools the sub-agent's actual deck, probed for `readOnly: true` flags
|
|
284
|
-
*/
|
|
285
|
-
export declare function createSubagentPermissionGate(policy: SessionPermissionPolicy, tools: ReadonlyArray<{
|
|
286
|
-
readonly name: string;
|
|
287
|
-
}>): CanUseToolFn;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permission rule engine + gate — unit tests.
|
|
3
|
-
*
|
|
4
|
-
* Exhaustively pins the pure decision ({@link resolveRuleDecision}) precedence
|
|
5
|
-
* (deny > plan-deny > ask > bypass > read-only > acceptEdits > allow > ask
|
|
6
|
-
* fallthrough), the induscode rule parsing/matching ({@link parseRule},
|
|
7
|
-
* {@link toolMatchesRule}, including argument specifiers and the `mcp__` wildcard),
|
|
8
|
-
* the mode behaviors, and the {@link createPermissionGate} `ask` routing — a host
|
|
9
|
-
* resolver returns allow-once / allow-always (which appends a session allow rule)
|
|
10
|
-
* / deny, and an ABSENT resolver denies. No framework, no network.
|
|
11
|
-
*/
|
|
12
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plan-mode round-trip — integration across the gate + the conductor handshake.
|
|
3
|
-
*
|
|
4
|
-
* Two proofs, against the REAL wired pieces (the rule engine's gate + the live
|
|
5
|
-
* conductor), not mocks of an unwired module:
|
|
6
|
-
*
|
|
7
|
-
* 1. **The gate denies edits in plan mode.** A `createPermissionGate` whose mode
|
|
8
|
-
* getter reads the conductor's LIVE `permissionMode()` allows an edit in
|
|
9
|
-
* `default` mode, denies it once the conductor enters plan mode
|
|
10
|
-
* (`togglePlanMode(true)` / `setPermissionMode('plan')`), and allows it again
|
|
11
|
-
* once an approved exit restores the prior mode. This is the exact gate the
|
|
12
|
-
* conductor threads into the framework `Agent`, so the deny lands where tools
|
|
13
|
-
* execute.
|
|
14
|
-
*
|
|
15
|
-
* 2. **ExitPlanMode approval restores the mode, persists the plan, and resumes.**
|
|
16
|
-
* A scripted fake agent emits a `tool_execution_end` carrying the
|
|
17
|
-
* `{ exitPlan: true, plan }` detail the conductor intercepts. With an approval
|
|
18
|
-
* resolver installed that approves, a turn run while in plan mode: restores
|
|
19
|
-
* the captured pre-plan mode, writes the plan to a file under `plansDir`, and
|
|
20
|
-
* enqueues the approved plan as a follow-up so the model proceeds from it. A
|
|
21
|
-
* rejecting resolver keeps the session in plan mode and writes nothing.
|
|
22
|
-
*/
|
|
23
|
-
export {};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conductor-integration tests for the post-edit live-diagnostics seam.
|
|
3
|
-
*
|
|
4
|
-
* Drives a scripted {@link AgentLike} that emits a `tool_execution_start` for an
|
|
5
|
-
* `edit`/`write` tool during `prompt`, with an injected {@link DiagnosticsEngine}
|
|
6
|
-
* over a scripted in-memory runner (no real tsc spawn). Verifies:
|
|
7
|
-
* - a turn that introduces a NEW diagnostic enqueues the summary follow-up;
|
|
8
|
-
* - a clean edit (no new diagnostics) enqueues nothing;
|
|
9
|
-
* - a still-unfixed diagnostic is delivered AT MOST ONCE per session — a
|
|
10
|
-
* follow-up turn whose "fix" edits fail to eliminate the same error must
|
|
11
|
-
* NOT be re-prompted with it (the endless self-continuation of issue #15);
|
|
12
|
-
* - even genuinely NEW errors per fix attempt stop re-prompting at the
|
|
13
|
-
* consecutive follow-up cap, and a fresh user prompt re-arms the budget;
|
|
14
|
-
* - `idle` is not emitted between a turn and its auto-drained follow-up (the
|
|
15
|
-
* spinner must not drop while the agent keeps working);
|
|
16
|
-
* - a non-TS edit never triggers the checker.
|
|
17
|
-
*/
|
|
18
|
-
export {};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* quota-error.ts — maps the indus model-gateway's usage-limit response into a
|
|
3
|
-
* friendly, user-facing fault message.
|
|
4
|
-
*
|
|
5
|
-
* When a no-local-key, logged-in user runs a turn, the framework adapter is
|
|
6
|
-
* pointed at `${INDUS_SERVER_URL}/gateway/<provider>` (see the conductor's
|
|
7
|
-
* baseUrl rewrite). If that user is over their monthly token allowance, the
|
|
8
|
-
* server replies — *before* forwarding upstream — with:
|
|
9
|
-
*
|
|
10
|
-
* HTTP/1.1 429 Too Many Requests
|
|
11
|
-
* Content-Type: application/json
|
|
12
|
-
*
|
|
13
|
-
* { "error": "quota_exceeded", "used": <number>, "limit": <number> }
|
|
14
|
-
*
|
|
15
|
-
* The provider SDK / raw-fetch adapter turns that 429 into a thrown error. By
|
|
16
|
-
* the time it reaches the conductor it may be wrapped (an SDK `APIError`, a
|
|
17
|
-
* generic `Error`, a nested `cause` chain, or a plain string), so detection must
|
|
18
|
-
* be tolerant and walk the whole error chain rather than trust a single shape.
|
|
19
|
-
*
|
|
20
|
-
* This module is intentionally transport-agnostic and dependency-free so it can
|
|
21
|
-
* be unit-tested in isolation and imported from the conductor's retry chokepoint
|
|
22
|
-
* without pulling in any network/runtime modules.
|
|
23
|
-
*/
|
|
24
|
-
/** Detects the gateway's 429 quota body anywhere in the error chain. */
|
|
25
|
-
export declare function isQuotaFault(error: unknown): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Friendly user-facing text; `undefined` if `error` is not a quota fault.
|
|
28
|
-
*
|
|
29
|
-
* Includes the `<used>/<limit>` parenthetical when both numbers are parseable,
|
|
30
|
-
* and otherwise falls back to the same sentence without it. The `indus signin
|
|
31
|
-
* <provider>` hint steers the user toward supplying their own key (which takes
|
|
32
|
-
* the direct, un-metered local-key path), and the upgrade hint covers raising
|
|
33
|
-
* the server-side allowance.
|
|
34
|
-
*/
|
|
35
|
-
export declare function quotaErrorMessage(error: unknown): string | undefined;
|