@datagusto/cli 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +186 -2
- package/bin/run.js +5 -0
- package/dist/adapters/claude-code.d.ts +47 -0
- package/dist/adapters/claude-code.js +533 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/claude-settings.d.ts +29 -0
- package/dist/adapters/claude-settings.js +115 -0
- package/dist/adapters/claude-settings.js.map +1 -0
- package/dist/adapters/index.d.ts +10 -0
- package/dist/adapters/index.js +37 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/kiro-agent.d.ts +29 -0
- package/dist/adapters/kiro-agent.js +124 -0
- package/dist/adapters/kiro-agent.js.map +1 -0
- package/dist/adapters/kiro.d.ts +24 -0
- package/dist/adapters/kiro.js +740 -0
- package/dist/adapters/kiro.js.map +1 -0
- package/dist/adapters/types.d.ts +79 -0
- package/dist/adapters/types.js +14 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/api/client.d.ts +36 -0
- package/dist/api/client.js +85 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/errors.d.ts +4 -0
- package/dist/api/errors.js +25 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/commands/remove.d.ts +13 -0
- package/dist/commands/remove.js +59 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/setup.d.ts +16 -0
- package/dist/commands/setup.js +114 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +53 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/display.d.ts +2 -0
- package/dist/display.js +8 -0
- package/dist/display.js.map +1 -0
- package/dist/fs/atomic.d.ts +17 -0
- package/dist/fs/atomic.js +41 -0
- package/dist/fs/atomic.js.map +1 -0
- package/dist/key-input.d.ts +24 -0
- package/dist/key-input.js +96 -0
- package/dist/key-input.js.map +1 -0
- package/dist/state/installs.d.ts +24 -0
- package/dist/state/installs.js +110 -0
- package/dist/state/installs.js.map +1 -0
- package/dist/vendor.d.ts +16 -0
- package/dist/vendor.js +60 -0
- package/dist/vendor.js.map +1 -0
- package/package.json +57 -4
- package/vendor/claude_code/.claude-plugin/plugin.json +55 -0
- package/vendor/claude_code/README.md +267 -0
- package/vendor/claude_code/dist/api-client.js +82 -0
- package/vendor/claude_code/dist/builtin-tools.generated.js +33 -0
- package/vendor/claude_code/dist/extractors.js +201 -0
- package/vendor/claude_code/dist/index.js +695 -0
- package/vendor/claude_code/dist/monitoring.js +66 -0
- package/vendor/claude_code/dist/state.js +71 -0
- package/vendor/claude_code/dist/types.js +5 -0
- package/vendor/claude_code/hooks/hooks.json +25 -0
- package/vendor/claude_code/package.json +26 -0
- package/vendor/kiro/.kiro/agents/kiro_default.json +20 -0
- package/vendor/kiro/.kiro/hooks/datagusto-post-tool-use.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-pre-tool-use.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-session-start.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-stop.json +10 -0
- package/vendor/kiro/.kiro/hooks/datagusto-user-prompt-submit.json +10 -0
- package/vendor/kiro/dist/api-client.js +82 -0
- package/vendor/kiro/dist/builtin-tools.generated.js +87 -0
- package/vendor/kiro/dist/engine.js +65 -0
- package/vendor/kiro/dist/extractors.js +201 -0
- package/vendor/kiro/dist/index.js +735 -0
- package/vendor/kiro/dist/monitoring.js +66 -0
- package/vendor/kiro/dist/state.js +71 -0
- package/vendor/kiro/dist/types.js +5 -0
- package/vendor/kiro/package.json +25 -0
- package/vendor/manifest.json +42 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Datagusto Safety Plugin - Monitoring-mode resolution
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Two independent switches can turn enforcement off:
|
|
6
|
+
//
|
|
7
|
+
// - the plugin's own `monitorOnly` config (a local staging-rollout knob), and
|
|
8
|
+
// - the platform's per-agent monitoring mode, surfaced by the server as
|
|
9
|
+
// `monitoring_mode_enabled` on /sessions/alignment and /sessions/validate
|
|
10
|
+
// responses.
|
|
11
|
+
//
|
|
12
|
+
// Either one being true means a verdict (deny / ask / block / inject) is
|
|
13
|
+
// logged but not enforced. The platform value is resolved per request:
|
|
14
|
+
// the validate response of the current call wins, then the value most
|
|
15
|
+
// recently reported by any alignment / validate response for this session
|
|
16
|
+
// (kept in session state), then false — older servers that omit the field
|
|
17
|
+
// behave as before.
|
|
18
|
+
//
|
|
19
|
+
// The platform value never changes fail-closed handling of API errors: the
|
|
20
|
+
// server's monitoring mode only says whether *verdicts* are enforced, and
|
|
21
|
+
// an errored request carries no verdict (and no flag) to begin with.
|
|
22
|
+
/**
|
|
23
|
+
* Read `monitoring_mode_enabled` from an API response body. Returns undefined
|
|
24
|
+
* when the field is absent or not a boolean so callers can fall back to the
|
|
25
|
+
* value cached in session state.
|
|
26
|
+
*/
|
|
27
|
+
export function readMonitoringFlag(data) {
|
|
28
|
+
if (data && typeof data === "object") {
|
|
29
|
+
const v = data.monitoring_mode_enabled;
|
|
30
|
+
if (typeof v === "boolean")
|
|
31
|
+
return v;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Combine the plugin's `monitorOnly` config with the platform's monitoring
|
|
37
|
+
* mode. `responseFlag` is the value from the current request's response (or
|
|
38
|
+
* undefined when that response has none), `stateFlag` the value cached from
|
|
39
|
+
* alignment (null when never seen).
|
|
40
|
+
*/
|
|
41
|
+
export function resolveMonitoring(pluginMonitorOnly, responseFlag, stateFlag) {
|
|
42
|
+
const platformEnabled = typeof responseFlag === "boolean" ? responseFlag : stateFlag === true;
|
|
43
|
+
const plugin = pluginMonitorOnly === true;
|
|
44
|
+
let source;
|
|
45
|
+
if (plugin && platformEnabled)
|
|
46
|
+
source = "plugin+platform";
|
|
47
|
+
else if (plugin)
|
|
48
|
+
source = "plugin";
|
|
49
|
+
else if (platformEnabled)
|
|
50
|
+
source = "platform";
|
|
51
|
+
return { active: plugin || platformEnabled, source, platformEnabled };
|
|
52
|
+
}
|
|
53
|
+
/** Human-readable label for log lines, e.g. "platform monitoring mode". */
|
|
54
|
+
export function describeMonitoring(decision) {
|
|
55
|
+
switch (decision.source) {
|
|
56
|
+
case "plugin":
|
|
57
|
+
return "plugin monitorOnly";
|
|
58
|
+
case "platform":
|
|
59
|
+
return "platform monitoring mode";
|
|
60
|
+
case "plugin+platform":
|
|
61
|
+
return "plugin monitorOnly + platform monitoring mode";
|
|
62
|
+
default:
|
|
63
|
+
return "enforcing";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=monitoring.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Datagusto Safety Plugin - Persisted Per-Session State
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// OpenClaw's plugin keeps state in memory inside one long-running process
|
|
6
|
+
// and has to detect session boundaries itself (see the OpenClaw plugin's
|
|
7
|
+
// `onNewTurn`). Claude Code hooks are the opposite: every invocation is a
|
|
8
|
+
// brand-new process that exits after handling one event, but each payload
|
|
9
|
+
// already carries a stable `session_id` for the lifetime of the
|
|
10
|
+
// conversation. So instead of an in-memory class with manual session-change
|
|
11
|
+
// detection, state is a small JSON blob on disk, namespaced by that
|
|
12
|
+
// session_id — no reset hook is needed because a new session simply reads
|
|
13
|
+
// and writes its own file.
|
|
14
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { tmpdir } from "node:os";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
const EMPTY_STATE = {
|
|
18
|
+
sessionId: null,
|
|
19
|
+
registeredToolsHash: null,
|
|
20
|
+
lastUserInstructionHash: null,
|
|
21
|
+
lastPreToolUseCheck: null,
|
|
22
|
+
monitoringModeEnabled: null,
|
|
23
|
+
monitoringNoticeShown: false,
|
|
24
|
+
};
|
|
25
|
+
const STATE_DIR = join(tmpdir(), "datagusto-safety-plugin");
|
|
26
|
+
function statePath(claudeSessionId) {
|
|
27
|
+
return join(STATE_DIR, `${claudeSessionId}.json`);
|
|
28
|
+
}
|
|
29
|
+
/** Load this Claude Code session's state, or an empty one if none exists yet. */
|
|
30
|
+
export function loadState(claudeSessionId) {
|
|
31
|
+
try {
|
|
32
|
+
const raw = readFileSync(statePath(claudeSessionId), "utf8");
|
|
33
|
+
return { ...EMPTY_STATE, ...JSON.parse(raw) };
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { ...EMPTY_STATE };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Persist this Claude Code session's state for the next hook invocation. */
|
|
40
|
+
export function saveState(claudeSessionId, state) {
|
|
41
|
+
mkdirSync(STATE_DIR, { recursive: true });
|
|
42
|
+
writeFileSync(statePath(claudeSessionId), JSON.stringify(state), "utf8");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Re-read the state file, apply `mutate` to the fresh copy, and write it back.
|
|
46
|
+
*
|
|
47
|
+
* Claude Code can run several hook processes for one session concurrently
|
|
48
|
+
* (parallel tool calls), and each handler awaits HTTP round-trips between
|
|
49
|
+
* its initial loadState() and any save. Writing back that stale snapshot
|
|
50
|
+
* would clobber fields another process persisted in the meantime, so
|
|
51
|
+
* handlers that only need to update a few fields after their awaits use
|
|
52
|
+
* this instead of saveState(). The read-modify-write is still unlocked —
|
|
53
|
+
* the window is the microseconds between the read and the write rather
|
|
54
|
+
* than the whole HTTP round-trip — which is adequate for these hints.
|
|
55
|
+
*/
|
|
56
|
+
export function mutateState(claudeSessionId, mutate) {
|
|
57
|
+
const fresh = loadState(claudeSessionId);
|
|
58
|
+
mutate(fresh);
|
|
59
|
+
saveState(claudeSessionId, fresh);
|
|
60
|
+
return fresh;
|
|
61
|
+
}
|
|
62
|
+
/** Remove this Claude Code session's state file (called from SessionEnd). */
|
|
63
|
+
export function deleteState(claudeSessionId) {
|
|
64
|
+
try {
|
|
65
|
+
rmSync(statePath(claudeSessionId), { force: true });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Best-effort cleanup — a failure here should never block SessionEnd.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
5
|
+
],
|
|
6
|
+
"SessionEnd": [
|
|
7
|
+
{ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
8
|
+
],
|
|
9
|
+
"UserPromptSubmit": [
|
|
10
|
+
{ "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
11
|
+
],
|
|
12
|
+
"PreToolUse": [
|
|
13
|
+
{ "matcher": "*", "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
14
|
+
],
|
|
15
|
+
"PermissionRequest": [
|
|
16
|
+
{ "matcher": "*", "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
17
|
+
],
|
|
18
|
+
"PostToolUse": [
|
|
19
|
+
{ "matcher": "*", "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
20
|
+
],
|
|
21
|
+
"PostToolUseFailure": [
|
|
22
|
+
{ "matcher": "*", "hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/index.js\"" }] }
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "datagusto-safety-plugin",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Datagusto safety validation plugin for Claude Code",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"typecheck": "tsc --noEmit",
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"prepublishOnly": "npm run build",
|
|
12
|
+
"test": "npm run build && node --test tests/*.test.mjs"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"src/",
|
|
17
|
+
".claude-plugin/",
|
|
18
|
+
"hooks/",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.0.0",
|
|
24
|
+
"typescript": "^6.0.3"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kiro_default",
|
|
3
|
+
"description": "Kiro's default agent with the Datagusto safety hooks",
|
|
4
|
+
"tools": ["*"],
|
|
5
|
+
"allowedTools": [],
|
|
6
|
+
"resources": [
|
|
7
|
+
"file://AmazonQ.md",
|
|
8
|
+
"file://AGENTS.md",
|
|
9
|
+
"file://README.md",
|
|
10
|
+
"skill://.kiro/skills/*/SKILL.md"
|
|
11
|
+
],
|
|
12
|
+
"includeMcpJson": true,
|
|
13
|
+
"hooks": {
|
|
14
|
+
"agentSpawn": [{ "command": "node dist/index.js", "description": "Datagusto safety", "timeout_ms": 30000 }],
|
|
15
|
+
"userPromptSubmit": [{ "command": "node dist/index.js", "description": "Datagusto safety", "timeout_ms": 30000 }],
|
|
16
|
+
"preToolUse": [{ "command": "node dist/index.js", "description": "Datagusto safety", "timeout_ms": 30000 }],
|
|
17
|
+
"postToolUse": [{ "command": "node dist/index.js", "description": "Datagusto safety", "timeout_ms": 30000 }],
|
|
18
|
+
"stop": [{ "command": "node dist/index.js", "description": "Datagusto safety", "timeout_ms": 30000 }]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Datagusto Safety Plugin - HTTP API Client
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
const TOOLS_REGISTER_PATH = "/api/v1/public/safety/tools/register";
|
|
5
|
+
const SESSIONS_ALIGNMENT_PATH = "/api/v1/public/safety/sessions/alignment";
|
|
6
|
+
const SESSIONS_VALIDATE_PATH = "/api/v1/public/safety/sessions/validate";
|
|
7
|
+
const GUARDRAILS_EVALUATE_PATH = "/api/v1/public/guardrails/evaluate";
|
|
8
|
+
export class DatagustoApiClient {
|
|
9
|
+
baseUrl;
|
|
10
|
+
apiKey;
|
|
11
|
+
timeoutMs;
|
|
12
|
+
constructor(baseUrl, apiKey, timeoutMs = 30_000) {
|
|
13
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
14
|
+
this.apiKey = apiKey;
|
|
15
|
+
this.timeoutMs = timeoutMs;
|
|
16
|
+
}
|
|
17
|
+
// -- Public API methods ---------------------------------------------------
|
|
18
|
+
async registerTools(tools) {
|
|
19
|
+
const body = { tools };
|
|
20
|
+
return this._post(TOOLS_REGISTER_PATH, body);
|
|
21
|
+
}
|
|
22
|
+
async postAlignment(userInstruction, sessionId, agentType) {
|
|
23
|
+
const body = { user_instruction: userInstruction };
|
|
24
|
+
if (sessionId) {
|
|
25
|
+
body.session_id = sessionId;
|
|
26
|
+
}
|
|
27
|
+
if (agentType) {
|
|
28
|
+
body.agent_type = agentType;
|
|
29
|
+
}
|
|
30
|
+
return this._post(SESSIONS_ALIGNMENT_PATH, body);
|
|
31
|
+
}
|
|
32
|
+
async postValidate(payload) {
|
|
33
|
+
return this._post(SESSIONS_VALIDATE_PATH, payload);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Evaluate the agent's assigned (dashboard-authored) guardrail rules for a
|
|
37
|
+
* single tool call. Agent-scoped via the API key — needs no session_id — and
|
|
38
|
+
* is the only path that evaluates assigned rules and on_end timing. Called
|
|
39
|
+
* alongside postValidate and merged (block-wins) by the hook handlers.
|
|
40
|
+
*/
|
|
41
|
+
async evaluateGuardrails(payload) {
|
|
42
|
+
return this._post(GUARDRAILS_EVALUATE_PATH, payload);
|
|
43
|
+
}
|
|
44
|
+
// -- Internal helper ------------------------------------------------------
|
|
45
|
+
async _post(endpoint, body) {
|
|
46
|
+
const url = this.baseUrl + endpoint;
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch(url, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
},
|
|
54
|
+
body: JSON.stringify(body),
|
|
55
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
56
|
+
});
|
|
57
|
+
const text = await response.text();
|
|
58
|
+
let data = null;
|
|
59
|
+
try {
|
|
60
|
+
data = text ? JSON.parse(text) : null;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Non-JSON response — leave data as null
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
ok: response.ok,
|
|
67
|
+
status: response.status,
|
|
68
|
+
data,
|
|
69
|
+
...(response.ok ? {} : { error: text }),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
status: null,
|
|
76
|
+
data: null,
|
|
77
|
+
error: err instanceof Error ? err.message : String(err),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// GENERATED by scripts/generate-builtin-tools.mjs — do not edit by hand.
|
|
2
|
+
// Sources:
|
|
3
|
+
// V1 tool index embedded in the Kiro CLI binary (kiro-cli-chat 2.27.1)
|
|
4
|
+
// V2, V3 tool calls observed in hook payloads (scripts/observed-tool-inputs.json,
|
|
5
|
+
// Kiro CLI 2.27.1)
|
|
6
|
+
// Tool counts: V1 18, V2 15, V3 18
|
|
7
|
+
//
|
|
8
|
+
// One catalog per Kiro agent engine. Tool ids are the names that engine sends
|
|
9
|
+
// as `tool_name` in hook payloads, so the same capability has a different id
|
|
10
|
+
// per engine (read a file: `fs_read` on V1, `read` on V2, `read_file` on V3),
|
|
11
|
+
// and two ids (`fs_write`, `execute_bash`) mean different things on V1 and
|
|
12
|
+
// V3. MCP tools are dynamic per-installation and intentionally excluded.
|
|
13
|
+
/** V1 engine (the setting `chat.agentEngine` = "v1", or `--agent-engine v1` per Kiro's help text). */
|
|
14
|
+
export const BUILTIN_TOOLS_V1 = [
|
|
15
|
+
{ "id": "fs_read", "description": "Read files, directories, and images", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "operations": { "type": "array", "description": "Array of operations to execute. Provide one element for single operation, multiple for batch.", "items": { "type": "object", "properties": { "mode": { "type": "string", "enum": ["Line", "Directory", "Search", "Image"], "description": "The operation mode to run in: `Line`, `Directory`, `Search`. `Line` and `Search` are only for text files, and `Directory` is only for directories. `Image` is for image files, in this mode `image_paths` is required." }, "path": { "type": "string", "description": "Path to the file or directory. The path should be absolute, or otherwise start with ~ for the user's home (required for Line, Directory, Search modes)." }, "image_paths": { "type": "array", "items": { "type": "string" }, "description": "List of paths to the images. This is currently supported by the Image mode." }, "start_line": { "type": "integer", "description": "Starting line number (optional, for Line mode). A negative index represents a line number starting from the end of the file.", "default": 1 }, "end_line": { "type": "integer", "description": "Ending line number (optional, for Line mode). A negative index represents a line number starting from the end of the file.", "default": -1 }, "pattern": { "type": "string", "description": "Pattern to search for (required, for Search mode). Case insensitive. The pattern matching is performed per line." }, "context_lines": { "type": "integer", "description": "Number of context lines around search results (optional, for Search mode)", "default": 2 }, "depth": { "type": "integer", "description": "Depth of a recursive directory listing (optional, for Directory mode)", "default": 0 }, "exclude_patterns": { "type": "array", "items": { "type": "string" }, "description": "Glob patterns to exclude from directory listing (optional, for Directory mode). If omitted, uses defaults. If empty array [] is provided, no exclusions are applied (shows everything). If patterns are provided, they completely override the defaults. Examples: '**/target/**', '*.log'", "default": ["node_modules", ".git", "dist", "build", "out", ".cache", "target"] }, "max_entries": { "type": "integer", "description": "Maximum number of entries to return (optional, for Directory mode). When limit is reached, results are truncated and metadata shows 'showing X of Y entries'. Use to prevent context window overflow. Default: 1000", "default": 1000 }, "offset": { "type": "integer", "description": "Number of entries to skip for pagination (optional, for Directory mode). Use with max_entries to iterate through large directories. Entries are sorted by last modified time (most recent first). Default: 0", "default": 0 } }, "required": ["mode"] }, "minItems": 1 }, "summary": { "type": "string", "description": "Optional description of the purpose of this batch operation (mainly useful for multiple operations)" } }, "required": ["operations"] }, "inputSchemaSource": "kiro-cli" },
|
|
16
|
+
{ "id": "fs_write", "description": "Create and modify files", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "command": { "type": "string", "enum": ["create", "str_replace", "insert", "append"], "description": "The commands to run. Allowed options are: `create`, `str_replace`, `insert`, `append`." }, "file_text": { "description": "Required parameter of `create` command, with the content of the file to be created.", "type": "string" }, "insert_line": { "description": "Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`.", "type": "integer" }, "new_str": { "description": "Required parameter of `str_replace` command containing the new string. Required parameter of `insert` command containing the string to insert. Required parameter of `append` command containing the content to append to the file.", "type": "string" }, "old_str": { "description": "Required parameter of `str_replace` command containing the string in `path` to replace.", "type": "string" }, "path": { "description": "Absolute path to file or directory, e.g. `/repo/file.py` or `/repo`.", "type": "string" }, "summary": { "description": "A brief explanation of what the file change does or why it's being made.", "type": "string" } }, "required": ["command", "path"] }, "inputSchemaSource": "kiro-cli" },
|
|
17
|
+
{ "id": "glob", "description": "Find files and directories matching glob patterns", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "pattern": { "type": "string", "description": "Glob pattern, e.g. '**/*.rs', 'src/**/*.{ts,tsx}' or '**/test*'." }, "path": { "type": "string", "description": "Root directory to search from. Only set this when the user explicitly mentions a directory path. In all other cases, omit this so the tool searches from the current working directory (the project root)." }, "limit": { "type": "integer", "description": "Maximum files to return. If totalFiles exceeds this, truncated will be true." }, "max_depth": { "type": "integer", "description": "Maximum directory depth to traverse. Increase for deep nested structures." } }, "required": ["pattern"] }, "inputSchemaSource": "kiro-cli" },
|
|
18
|
+
{ "id": "grep", "description": "Search file contents with a regex", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "pattern": { "type": "string", "description": "Regex pattern to search for. Examples: 'fn main', 'class.*Component', 'TODO|FIXME'. Start with simple patterns first (e.g. just the word you're looking for), then refine if needed." }, "path": { "type": "string", "description": "Directory to search from. Defaults to current working directory." }, "include": { "type": "string", "description": "File filter glob. Examples: '*.rs', '*.{ts,tsx}', '*.py'" }, "case_sensitive": { "type": "boolean", "description": "Case-sensitive search. Defaults to false (case-insensitive)." }, "output_mode": { "type": "string", "enum": ["content", "files_with_matches", "count"], "description": "Output format: 'content' returns matches as 'file:line:content' (default, best for seeing actual matches), 'files_with_matches' returns only file paths, 'count' returns match counts per file." }, "max_matches_per_file": { "type": "integer", "description": "Max matches returned per file (output limit). Increase to see all occurrences in a file." }, "max_files": { "type": "integer", "description": "Max number of files returned (output limit). Increase for comprehensive codebase searches." }, "max_total_lines": { "type": "integer", "description": "Max total matched lines returned across all files (output limit). Increase when searching for many occurrences." }, "max_depth": { "type": "integer", "description": "Max directory depth to traverse when searching (search limit). Increase for deeply nested structures." } }, "required": ["pattern"] }, "inputSchemaSource": "kiro-cli" },
|
|
19
|
+
{ "id": "execute_bash", "description": "Execute a shell command", "sectionId": "runtime", "sectionLabel": "Shell", "inputSchema": { "type": "object", "properties": { "command": { "type": "string", "description": "Bash command to execute" }, "summary": { "type": "string", "description": "A brief explanation of what the command does" }, "working_dir": { "type": "string", "description": "Working directory for command execution. Supports tilde expansion (e.g., ~/projects). If not specified, uses the current working directory." } }, "required": ["command"] }, "inputSchemaSource": "kiro-cli" },
|
|
20
|
+
{ "id": "use_aws", "description": "Make AWS CLI API calls", "sectionId": "aws", "sectionLabel": "AWS", "inputSchema": { "type": "object", "properties": { "service_name": { "type": "string", "pattern": "^[^-].*", "description": "The name of the AWS service. If you want to query s3, you should use s3api if possible. Must not start with a dash (-)." }, "operation_name": { "type": "string", "description": "The name of the operation to perform." }, "positional_args": { "type": "array", "items": { "type": "string" }, "description": "Positional arguments for high-level commands (e.g., s3 cp, s3 mv, s3 sync, s3 rm). These are passed directly without -- prefix. Use this for source/destination paths in S3 commands." }, "parameters": { "type": "object", "description": "The parameters for the operation. The parameter keys MUST conform to the AWS CLI specification. You should prefer to use JSON Syntax over shorthand syntax wherever possible. For parameters that are booleans, prioritize using flags with no value. Denote these flags with flag names as key and an empty string as their value. You should also prefer kebab case." }, "region": { "type": "string", "description": "Region name for calling the operation on AWS." }, "profile_name": { "type": "string", "description": "Optional: AWS profile name to use from ~/.aws/credentials. Defaults to default profile if not specified." }, "label": { "type": "string", "description": "Human readable description of the api that is being called." } }, "required": ["region", "service_name", "operation_name", "label"] }, "inputSchemaSource": "kiro-cli" },
|
|
21
|
+
{ "id": "web_search", "description": "Search the web", "sectionId": "web", "sectionLabel": "Web", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "maxLength": 200, "description": "Search query (max 200 chars) - use concise keywords, not full sentences" } }, "required": ["query"] }, "inputSchemaSource": "kiro-cli" },
|
|
22
|
+
{ "id": "web_fetch", "description": "Fetch and extract content from a URL", "sectionId": "web", "sectionLabel": "Web", "inputSchema": { "type": "object", "properties": { "url": { "type": "string", "description": "URL to fetch content from" }, "mode": { "type": "string", "enum": ["selective", "truncated", "full"], "description": "Extraction mode: 'selective' for smart extraction (default), 'truncated' for first 8000 chars, 'full' for complete content" }, "search_terms": { "type": "string", "description": "Optional: Keywords to find in selective mode (e.g., 'pricing cost', 'installation setup'). Returns ~10 lines before and after matches. If not provided, returns beginning of page." } }, "required": ["url"] }, "inputSchemaSource": "kiro-cli" },
|
|
23
|
+
{ "id": "delegate", "description": "Launch and manage background agent processes", "sectionId": "agents", "sectionLabel": "Agents", "inputSchema": { "type": "object", "properties": { "operation": { "description": "Operation to perform: launch, status, or list", "$ref": "#/$defs/Operation" }, "agent": { "description": "Agent name to use (optional - uses \"q_cli_default\" if not specified)", "type": ["string", "null"], "default": null }, "task": { "description": "Task description (required for launch operation). This process is supposed to be async. DO NOT query immediately after launching a task.", "type": ["string", "null"], "default": null } }, "required": ["operation"], "$defs": { "Operation": { "oneOf": [{ "description": "Launch a new agent with a specified task", "type": "string", "const": "launch" }, { "description": "Check the status of a specific agent or all agents if None is provided", "type": "object", "properties": { "status": { "type": ["string", "null"] } }, "required": ["status"], "additionalProperties": false }, { "description": "List all available agents", "type": "string", "const": "list" }] } } }, "inputSchemaSource": "kiro-cli" },
|
|
24
|
+
{ "id": "use_subagent", "description": "Delegate tasks to subagents running in parallel", "sectionId": "agents", "sectionLabel": "Agents", "inputSchema": { "type": "object", "properties": { "command": { "type": "string", "enum": ["ListAgents", "InvokeSubagents"], "description": "The commands to run. Allowed options are `ListAgents` to query available agents, or `InvokeSubagents` to invoke one or more subagents" }, "content": { "description": "Required for `InvokeSubagents` command. Contains subagents array and optional conversation ID.", "type": "object", "properties": { "subagents": { "type": "array", "description": "Array of subagent invocations to execute in parallel. Each invocation specifies a query, optional agent name, and optional context.", "items": { "type": "object", "properties": { "query": { "type": "string", "description": "The query or task to be handled by the subagent" }, "agent_name": { "type": "string", "description": "Optional name of the specific agent to use. If not provided, uses the default agent" }, "relevant_context": { "type": "string", "description": "Optional additional context that should be provided to the subagent to help it understand the task better" } }, "required": ["query"] } } }, "required": ["subagents"] } }, "required": ["command"] }, "inputSchemaSource": "kiro-cli" },
|
|
25
|
+
{ "id": "todo_list", "description": "Create and manage TODO lists for multi-step tasks", "sectionId": "workflow", "sectionLabel": "Workflow", "inputSchema": { "type": "object", "properties": { "command": { "type": "string", "enum": ["create", "complete", "load", "add", "remove", "lookup"], "description": "The command to run. Allowed options are `create`, `complete`, `load`, `add`, `remove`, and `lookup`. Call `lookup` without arguments to see a list of all existing TODO list IDs." }, "tasks": { "description": "Required parameter of `create` command containing the list of DISTINCT tasks to be added to the TODO list.", "type": "array", "items": { "type": "object", "properties": { "task_description": { "type": "string", "description": "The main task description" }, "details": { "type": "string", "description": "Optional detailed information about the task" } }, "required": ["task_description"] } }, "todo_list_description": { "description": "Required parameter of `create` command containing a BRIEF summary of the todo list being created. The summary should be detailed enough to refer to without knowing the problem context beforehand.", "type": "string" }, "completed_indices": { "description": "Required parameter of `complete` command containing the 0-INDEXED numbers of EVERY completed task. Each task should be marked as completed IMMEDIATELY after it is finished.", "type": "array", "items": { "type": "integer" } }, "context_update": { "description": "Required parameter of `complete` command containing important task context. Use this command to track important information about the task AND information about files you have read.", "type": "string" }, "modified_files": { "description": "Optional parameter of `complete` command containing a list of paths of files that were modified during the task. This is useful for tracking file changes that are important to the task.", "type": "array", "items": { "type": "string" } }, "load_id": { "description": "Required parameter of `load` command containing ID of todo list to load", "type": "string" }, "current_id": { "description": "Required parameter of `complete`, `add`, and `remove` commands containing the ID of the currently loaded todo list. The ID will ALWAYS be provided after every `todo_list` call after the serialized todo list state.", "type": "string" }, "new_tasks": { "description": "Required parameter of `add` command containing a list of new tasks to be added to the to-do list.", "type": "array", "items": { "type": "object", "properties": { "task_description": { "type": "string", "description": "The main task description" }, "details": { "type": "string", "description": "Optional detailed information about the task" } }, "required": ["task_description"] } }, "insert_indices": { "description": "Required parameter of `add` command containing a list of 0-INDEXED positions to insert the new tasks. There MUST be an index for every new task being added.", "type": "array", "items": { "type": "integer" } }, "new_description": { "description": "Optional parameter of `add` and `remove` containing a new todo list description. Use this when the updated set of tasks significantly change the goal or overall procedure of the todo list.", "type": "string" }, "remove_indices": { "description": "Required parameter of `remove` command containing a list of 0-INDEXED positions of tasks to remove.", "type": "array", "items": { "type": "integer" } } }, "required": ["command"] }, "inputSchemaSource": "kiro-cli" },
|
|
26
|
+
{ "id": "thinking", "description": "Internal reasoning for complex problems", "sectionId": "workflow", "sectionLabel": "Workflow", "inputSchema": { "type": "object", "properties": { "thought": { "type": "string", "description": "A reflective note or intermediate reasoning step such as \"The user needs to prepare their application for production. I need to complete three major asks including 1: building their code from source, 2: bundling their release artifacts together, and 3: signing the application bundle." } }, "required": ["thought"] }, "inputSchemaSource": "kiro-cli" },
|
|
27
|
+
{ "id": "switch_to_execution", "description": "Switch from planning to execution mode", "sectionId": "workflow", "sectionLabel": "Workflow", "inputSchema": { "type": "object", "properties": { "plan": { "type": "string", "description": "The generated implementation plan" } }, "required": ["plan"] }, "inputSchemaSource": "kiro-cli" },
|
|
28
|
+
{ "id": "introspect", "description": "Answer questions about Kiro CLI capabilities and documentation", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "The user's question about this assistant's usage, features, or capabilities" }, "doc_path": { "type": "string", "description": "Path to a specific doc to retrieve (e.g., \"features/tangent-mode.md\"). Use this to get full content of a doc from the index." } }, "required": [] }, "inputSchemaSource": "kiro-cli" },
|
|
29
|
+
{ "id": "knowledge", "description": "Store and retrieve information across chat sessions", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "command": { "type": "string", "enum": ["show", "add", "remove", "clear", "search", "update", "status", "cancel"], "description": "The knowledge operation to perform:\n- 'show': List all knowledge contexts (no additional parameters required)\n- 'add': Add content to knowledge base (requires 'name' and 'value')\n- 'remove': Remove content from knowledge base (requires one of: 'name', 'context_id', or 'path')\n- 'clear': Remove all knowledge contexts.\n- 'search': Search across knowledge contexts (requires 'query', optional: 'context_id', 'limit', 'offset', 'snippet_length', 'sort_by', 'file_type')\n- 'update': Update existing context with new content (requires 'path' and one of: 'name', 'context_id')\n- 'status': Show background operation status and progress\n- 'cancel': Cancel background operations (optional 'operation_id' to cancel specific operation, or cancel all if not provided)" }, "name": { "type": "string", "description": "A descriptive name for the knowledge context. Required for 'add' operations. Can be used for 'remove' and 'update' operations to identify the context." }, "value": { "type": "string", "description": "The content to store in knowledge base. Required for 'add' operations. Can be either text content or a file/directory path. If it's a valid file or directory path, the content will be indexed; otherwise it's treated as text." }, "context_id": { "type": "string", "description": "The unique context identifier for targeted operations. Can be obtained from 'show' command. Used for 'remove', 'update', and 'search' operations to specify which context to operate on." }, "path": { "type": "string", "description": "File or directory path. Used in 'remove' operations to remove contexts by their source path, and required for 'update' operations to specify the new content location." }, "query": { "type": "string", "description": "The search query string. Required for 'search' operations. Performs semantic search across knowledge contexts to find relevant content." }, "limit": { "type": "integer", "description": "Maximum number of search results to return, use default value unless required more results or focused search. Optional for 'search' operations." }, "offset": { "type": "integer", "description": "Number of results to skip for pagination. Optional for 'search' operations." }, "snippet_length": { "type": "integer", "description": "Maximum character length for text snippets in results. Text longer than this will be truncated. Optional for 'search' operations." }, "sort_by": { "type": "string", "enum": ["relevance", "path", "name"], "description": "Sort order for search results. Options: 'relevance' (default, by similarity score), 'path' or 'name' (alphabetically by file path). Optional for 'search' operations." }, "file_type": { "type": "string", "description": "Filter results by file type (e.g., 'Code', 'Markdown', 'Text'). Optional for 'search' operations." }, "operation_id": { "type": "string", "description": "Optional operation ID to cancel a specific operation. Used with 'cancel' command. If not provided, all active operations will be cancelled. Can be either the full operation ID or the short 8-character ID." } }, "required": ["command"] }, "inputSchemaSource": "kiro-cli" },
|
|
30
|
+
{ "id": "session", "description": "Adjust session settings temporarily", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "operation": { "type": "string", "enum": ["list", "get", "set", "reset"], "description": "The operation to perform: 'list' shows configured settings, 'get' retrieves a specific setting, 'set' changes a setting value temporarily, 'reset' clears session override(s)" }, "key": { "type": "string", "description": "Setting key (e.g., 'chat.disableMarkdownRendering'). Required for 'get' and 'set' operations. Optional for 'reset' (if omitted, resets all session overrides). MUST be verified with introspect tool first." }, "value": { "description": "Value to set. Type depends on the setting (boolean, string, or number). Required for 'set' operation" } }, "required": ["operation"] }, "inputSchemaSource": "kiro-cli" },
|
|
31
|
+
{ "id": "report_issue", "description": "Open a pre-filled GitHub issue for Kiro CLI", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "title": { "type": "string", "description": "The title of the GitHub issue." }, "expected_behavior": { "type": "string", "description": "Optional: The expected chat behavior or action that did not happen." }, "actual_behavior": { "type": "string", "description": "Optional: The actual chat behavior that happened and demonstrates the issue or lack of a feature." }, "steps_to_reproduce": { "type": "string", "description": "Optional: Previous user chat requests or steps that were taken that may have resulted in the issue or error response." } }, "required": ["title"] }, "inputSchemaSource": "kiro-cli" },
|
|
32
|
+
{ "id": "code", "description": "Code intelligence operations such as symbol search", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "operation": { "type": "string" }, "symbol_name": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
33
|
+
];
|
|
34
|
+
/** V2 engine (plain `kiro-cli`, the default in Kiro CLI 2.x). */
|
|
35
|
+
export const BUILTIN_TOOLS_V2 = [
|
|
36
|
+
{ "id": "read", "description": "Read files, directories, and images", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "operations": { "type": "array", "items": { "type": "object", "properties": { "mode": { "type": "string" }, "path": { "type": "string" } } } } } }, "inputSchemaSource": "observed" },
|
|
37
|
+
{ "id": "write", "description": "Create and modify files", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "command": { "type": "string" }, "path": { "type": "string" }, "content": { "type": "string" }, "oldStr": { "type": "string" }, "newStr": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
38
|
+
{ "id": "glob", "description": "Find files and directories matching glob patterns", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "pattern": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
39
|
+
{ "id": "grep", "description": "Search file contents with a regex", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "pattern": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
40
|
+
{ "id": "code", "description": "Code intelligence operations such as symbol search", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "operation": { "type": "string" }, "symbol_name": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
41
|
+
{ "id": "shell", "description": "Execute a shell command", "sectionId": "runtime", "sectionLabel": "Shell", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "command": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
42
|
+
{ "id": "use_aws", "description": "Make AWS CLI API calls", "sectionId": "aws", "sectionLabel": "AWS", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "region": { "type": "string" }, "service_name": { "type": "string" }, "operation_name": { "type": "string" }, "label": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
43
|
+
{ "id": "web_search", "description": "Search the web", "sectionId": "web", "sectionLabel": "Web", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "query": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
44
|
+
{ "id": "web_fetch", "description": "Fetch and extract content from a URL", "sectionId": "web", "sectionLabel": "Web", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "url": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
45
|
+
{ "id": "subagent", "description": "Run a task through one or more subagent stages", "sectionId": "agents", "sectionLabel": "Agents", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "task": { "type": "string" }, "stages": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "role": { "type": "string" }, "prompt_template": { "type": "string" } } } } } }, "inputSchemaSource": "observed" },
|
|
46
|
+
{ "id": "todo_list", "description": "Create and manage TODO lists for multi-step tasks", "sectionId": "workflow", "sectionLabel": "Workflow", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "command": { "type": "string" }, "task_list_description": { "type": "string" }, "tasks": { "type": "array", "items": { "type": "object", "properties": { "task_description": { "type": "string" } } } } } }, "inputSchemaSource": "observed" },
|
|
47
|
+
{ "id": "goal", "description": "Track and complete the session's goal", "sectionId": "workflow", "sectionLabel": "Workflow", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "command": { "type": "string" }, "summary": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
48
|
+
{ "id": "switch_to_execution", "description": "Switch from planning to execution mode", "sectionId": "workflow", "sectionLabel": "Workflow", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "plan": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
49
|
+
{ "id": "introspect", "description": "Answer questions about Kiro CLI capabilities and documentation", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "__tool_use_purpose": { "type": "string" }, "query": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
50
|
+
{ "id": "knowledge", "description": "Store and retrieve information across chat sessions", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "command": { "type": "string" }, "name": { "type": "string" }, "value": { "type": "string" }, "__tool_use_purpose": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
51
|
+
];
|
|
52
|
+
/** V3 engine (`kiro-cli --v3`). */
|
|
53
|
+
export const BUILTIN_TOOLS_V3 = [
|
|
54
|
+
{ "id": "read_file", "description": "Read a file, optionally a range of lines", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "path": { "type": "string" }, "offset": { "description": "Optional. Only null has been observed." }, "limit": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
55
|
+
{ "id": "list_directory", "description": "List the contents of a directory", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "path": { "type": "string" }, "explanation": { "description": "Optional. Only null has been observed." }, "depth": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
56
|
+
{ "id": "fs_write", "description": "Create a file with the given text", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "path": { "type": "string" }, "text": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
57
|
+
{ "id": "fs_append", "description": "Append text to a file", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "path": { "type": "string" }, "text": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
58
|
+
{ "id": "str_replace", "description": "Replace a string in a file", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "path": { "type": "string" }, "oldStr": { "type": "string" }, "newStr": { "type": "string" }, "replace_all": { "type": "boolean" } } }, "inputSchemaSource": "observed" },
|
|
59
|
+
{ "id": "delete_file", "description": "Delete a file", "sectionId": "fs", "sectionLabel": "Files", "inputSchema": { "type": "object", "properties": { "explanation": { "type": "string" }, "targetFile": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
60
|
+
{ "id": "file_search", "description": "Find files by name or glob pattern", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "explanation": { "type": "string" }, "query": { "type": "string" }, "excludePattern": { "description": "Optional. Only null has been observed." }, "includeIgnoredFiles": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
61
|
+
{ "id": "grep_search", "description": "Search file contents with a regex", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "query": { "type": "string" }, "caseSensitive": { "description": "Optional. Only null has been observed." }, "excludePattern": { "description": "Optional. Only null has been observed." }, "explanation": { "description": "Optional. Only null has been observed." }, "includePattern": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
62
|
+
{ "id": "code", "description": "Code intelligence operations such as symbol search", "sectionId": "search", "sectionLabel": "Search", "inputSchema": { "type": "object", "properties": { "operation": { "type": "string" }, "file_path": { "description": "Optional. Only null has been observed." }, "symbol_name": { "type": "string" }, "symbols": { "type": "array" }, "path": { "description": "Optional. Only null has been observed." }, "symbol_type": { "description": "Optional. Only null has been observed." }, "limit": { "description": "Optional. Only null has been observed." }, "exact_match": { "description": "Optional. Only null has been observed." }, "language": { "description": "Optional. Only null has been observed." }, "include_source": { "description": "Optional. Only null has been observed." }, "top_level_only": { "description": "Optional. Only null has been observed." }, "pattern": { "description": "Optional. Only null has been observed." }, "replacement": { "description": "Optional. Only null has been observed." }, "row": { "description": "Optional. Only null has been observed." }, "column": { "description": "Optional. Only null has been observed." }, "new_name": { "description": "Optional. Only null has been observed." }, "trigger_character": { "description": "Optional. Only null has been observed." }, "tab_size": { "description": "Optional. Only null has been observed." }, "insert_spaces": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
63
|
+
{ "id": "execute_bash", "description": "Execute a shell command", "sectionId": "runtime", "sectionLabel": "Shell", "inputSchema": { "type": "object", "properties": { "command": { "type": "string" }, "description": { "type": ["string", "null"] }, "cwd": { "description": "Optional. Only null has been observed." }, "run_in_background": { "type": "boolean" }, "timeout": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
64
|
+
{ "id": "remote_web_search", "description": "Search the web", "sectionId": "web", "sectionLabel": "Web", "inputSchema": { "type": "object", "properties": { "query": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
65
|
+
{ "id": "web_fetch", "description": "Fetch and extract content from a URL", "sectionId": "web", "sectionLabel": "Web", "inputSchema": { "type": "object", "properties": { "url": { "type": "string" }, "mode": { "type": "string" }, "searchPhrase": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
66
|
+
{ "id": "orchestrate_subagent", "description": "Run a task through one or more subagent stages", "sectionId": "agents", "sectionLabel": "Agents", "inputSchema": { "type": "object", "properties": { "task": { "type": "string" }, "stages": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "role": { "type": "string" }, "prompt_template": { "type": "string" } } } }, "repeat": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
67
|
+
{ "id": "update_session_information", "description": "Update the session's title, description, or status", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "title": { "type": "string" }, "description": { "description": "Optional. Only null has been observed." }, "status": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
68
|
+
{ "id": "disclose_context", "description": "Load a named context, such as a skill, into the session", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "name": { "type": "string" } } }, "inputSchemaSource": "observed" },
|
|
69
|
+
{ "id": "kiro_powers", "description": "List and use Kiro powers", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "action": { "type": "string" }, "powerName": { "description": "Optional. Only null has been observed." }, "serverName": { "description": "Optional. Only null has been observed." }, "toolName": { "description": "Optional. Only null has been observed." }, "arguments": { "description": "Optional. Only null has been observed." }, "steeringFile": { "description": "Optional. Only null has been observed." }, "skillName": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
70
|
+
{ "id": "knowledge", "description": "Store and retrieve information across chat sessions", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "command": { "type": "string" }, "name": { "type": "string" }, "value": { "type": "string" }, "include": { "description": "Optional. Only null has been observed." }, "exclude": { "description": "Optional. Only null has been observed." }, "index_type": { "description": "Optional. Only null has been observed." }, "context_id": { "description": "Optional. Only null has been observed." }, "path": { "description": "Optional. Only null has been observed." }, "query": { "description": "Optional. Only null has been observed." }, "limit": { "description": "Optional. Only null has been observed." }, "offset": { "description": "Optional. Only null has been observed." }, "snippet_length": { "description": "Optional. Only null has been observed." }, "sort_by": { "description": "Optional. Only null has been observed." }, "file_type": { "description": "Optional. Only null has been observed." }, "operation_id": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
71
|
+
{ "id": "createHook", "description": "Create a Kiro hook", "sectionId": "kiro", "sectionLabel": "Kiro", "inputSchema": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "description": { "description": "Optional. Only null has been observed." }, "trigger": { "type": "string" }, "matcher": { "description": "Optional. Only null has been observed." }, "actionType": { "type": "string" }, "command": { "description": "Optional. Only null has been observed." }, "prompt": { "type": "string" }, "timeout": { "description": "Optional. Only null has been observed." } } }, "inputSchemaSource": "observed" },
|
|
72
|
+
];
|
|
73
|
+
export const BUILTIN_TOOLS_BY_ENGINE = {
|
|
74
|
+
v1: BUILTIN_TOOLS_V1,
|
|
75
|
+
v2: BUILTIN_TOOLS_V2,
|
|
76
|
+
v3: BUILTIN_TOOLS_V3,
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The default engine's catalog under the name the shared extractors.ts
|
|
80
|
+
* imports. Nothing in the Kiro plugin registers through it any more:
|
|
81
|
+
* index.ts builds the running engine's catalog in engine.ts, and
|
|
82
|
+
* extractors.ts's `buildBuiltinToolDefinitions` is unused here. The alias
|
|
83
|
+
* exists so that extractors.ts still compiles while staying byte-identical
|
|
84
|
+
* with the Claude Code plugin's copy.
|
|
85
|
+
*/
|
|
86
|
+
export const BUILTIN_TOOLS = BUILTIN_TOOLS_V2;
|
|
87
|
+
//# sourceMappingURL=builtin-tools.generated.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Datagusto Safety Plugin - Kiro agent engine detection
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Kiro CLI 2.x has three agent engines. They send different tool names and
|
|
6
|
+
// input shapes in their hook payloads, so the plugin registers the tool
|
|
7
|
+
// catalog of the engine that is actually running (see
|
|
8
|
+
// builtin-tools.generated.ts). Nothing in the payload names the engine; it is
|
|
9
|
+
// told apart by how the payload is spelled:
|
|
10
|
+
//
|
|
11
|
+
// hook_event_name session_id
|
|
12
|
+
// V1 camelCase (`preToolUse`) absent
|
|
13
|
+
// V2 camelCase (`preToolUse`) present (a uuid)
|
|
14
|
+
// V3 PascalCase (`PreToolUse`) present (`sess_<uuid>`)
|
|
15
|
+
//
|
|
16
|
+
// V2 is plain `kiro-cli`, the default. V1 runs when the Kiro setting
|
|
17
|
+
// `chat.agentEngine` is "v1"; `kiro-cli chat --help` also lists
|
|
18
|
+
// `--agent-engine v1`, which has not been run here. V3 is `kiro-cli --v3`.
|
|
19
|
+
//
|
|
20
|
+
// Tool names are never translated between engines: guardrails and the
|
|
21
|
+
// dashboard see the name the engine sent.
|
|
22
|
+
import { BUILTIN_TOOLS_BY_ENGINE } from "./builtin-tools.generated.js";
|
|
23
|
+
/** The engine used when a payload does not identify one: Kiro CLI 2.x's default. */
|
|
24
|
+
export const DEFAULT_ENGINE = "v2";
|
|
25
|
+
const V3_EVENTS = new Set(["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop"]);
|
|
26
|
+
const V1_V2_EVENTS = new Set(["agentSpawn", "userPromptSubmit", "preToolUse", "postToolUse", "stop"]);
|
|
27
|
+
/**
|
|
28
|
+
* Which Kiro engine wrote this hook payload.
|
|
29
|
+
*
|
|
30
|
+
* Only the exact event spellings Kiro sends are recognized. Anything else
|
|
31
|
+
* (another spelling, a missing or unknown event name) falls back to the
|
|
32
|
+
* default engine with `recognized: false`. This decides which catalog is
|
|
33
|
+
* registered and nothing else: how an event is dispatched and whether a call
|
|
34
|
+
* is blocked do not depend on it.
|
|
35
|
+
*/
|
|
36
|
+
export function detectEngine(payload) {
|
|
37
|
+
const event = payload.hook_event_name;
|
|
38
|
+
if (typeof event === "string") {
|
|
39
|
+
if (V3_EVENTS.has(event))
|
|
40
|
+
return { engine: "v3", recognized: true };
|
|
41
|
+
if (V1_V2_EVENTS.has(event)) {
|
|
42
|
+
const hasSession = typeof payload.session_id === "string" && payload.session_id.length > 0;
|
|
43
|
+
return { engine: hasSession ? "v2" : "v1", recognized: true };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { engine: DEFAULT_ENGINE, recognized: false };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The built-in tool catalog of `engine`, in the shape /tools/register takes.
|
|
50
|
+
*
|
|
51
|
+
* This replaces `buildBuiltinToolDefinitions()` from extractors.ts, which
|
|
52
|
+
* only knows one catalog. That function and the `BUILTIN_TOOLS` export it
|
|
53
|
+
* reads are now unused in this plugin; they stay because extractors.ts is
|
|
54
|
+
* kept byte-identical with the Claude Code plugin's copy.
|
|
55
|
+
*/
|
|
56
|
+
export function buildToolDefinitions(engine) {
|
|
57
|
+
return BUILTIN_TOOLS_BY_ENGINE[engine].map((t) => ({
|
|
58
|
+
name: t.id,
|
|
59
|
+
description: t.description,
|
|
60
|
+
input_schema: t.inputSchema,
|
|
61
|
+
// Kiro does not expose output schemas.
|
|
62
|
+
output_schema: { type: "object", properties: {} },
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=engine.js.map
|