@integrity-labs/agt-cli 0.10.1 → 0.10.2

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.
@@ -215,6 +215,25 @@ var INTEGRATION_REGISTRY = [
215
215
  },
216
216
  docs_url: "https://github.com/Pika-Labs/Pika-Skills"
217
217
  },
218
+ {
219
+ id: "claude-code",
220
+ name: "Claude Code",
221
+ category: "code",
222
+ description: "Claude Code AI agent runtime \u2014 code editing, task execution, file management, and development workflows",
223
+ supported_auth_types: ["api_key", "none"],
224
+ capabilities: [
225
+ { id: "claude-code:edit-code", name: "Edit Code", description: "Read, write, and edit source files", access: "write" },
226
+ { id: "claude-code:run-tasks", name: "Run Tasks", description: "Execute bash commands and development tasks", access: "write" },
227
+ { id: "claude-code:search", name: "Search Code", description: "Search files and grep codebase", access: "read" },
228
+ { id: "claude-code:git", name: "Git Operations", description: "Commit, branch, push, and manage version control", access: "write" }
229
+ ],
230
+ cli_tool: {
231
+ package: "@anthropic-ai/claude-code",
232
+ binary: "claude",
233
+ env_key: "ANTHROPIC_API_KEY"
234
+ },
235
+ docs_url: "https://docs.anthropic.com/en/docs/claude-code"
236
+ },
218
237
  {
219
238
  id: "custom",
220
239
  name: "Custom Integration",
@@ -1333,6 +1352,38 @@ ${entry.content}`
1333
1352
  return changed;
1334
1353
  }, codeName);
1335
1354
  },
1355
+ executePluginHook(ctx) {
1356
+ const agentDir = join(AUGMENTED_DIR, ctx.codeName);
1357
+ const projectDir = join(agentDir, "project");
1358
+ mkdirSync(agentDir, { recursive: true });
1359
+ const startedAt = Date.now();
1360
+ return new Promise((resolve3) => {
1361
+ const child = execFile("bash", ["-c", ctx.script], {
1362
+ cwd: agentDir,
1363
+ timeout: 6e4,
1364
+ maxBuffer: 1024 * 1024,
1365
+ env: {
1366
+ ...process.env,
1367
+ AGENT_CODE_NAME: ctx.codeName,
1368
+ AGENT_DIR: agentDir,
1369
+ AGENT_PROJECT_DIR: projectDir,
1370
+ AGENT_FRAMEWORK: "openclaw"
1371
+ }
1372
+ }, (error, stdout, stderr) => {
1373
+ const durationMs = Date.now() - startedAt;
1374
+ const timedOut = !!error && error.code === "ETIMEDOUT";
1375
+ resolve3({
1376
+ exitCode: error ? typeof error.code === "number" ? error.code : 1 : 0,
1377
+ stdout: stdout?.toString() ?? "",
1378
+ stderr: stderr?.toString() ?? "",
1379
+ durationMs,
1380
+ timedOut
1381
+ });
1382
+ });
1383
+ child.on("error", () => {
1384
+ });
1385
+ });
1386
+ },
1336
1387
  readGatewayToken(codeName) {
1337
1388
  const homeDir = getHomeDir();
1338
1389
  try {
@@ -1811,6 +1862,7 @@ registerFramework(nemoClawAdapter);
1811
1862
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3, chmodSync as chmodSync3 } from "fs";
1812
1863
  import { join as join3, relative } from "path";
1813
1864
  import { homedir as homedir2 } from "os";
1865
+ import { execFile as execFile3 } from "child_process";
1814
1866
 
1815
1867
  // ../../packages/core/dist/provisioning/frameworks/claudecode/identity.js
1816
1868
  function buildMemorySection(hasQmd) {
@@ -2190,6 +2242,88 @@ function provisionStopHook(codeName) {
2190
2242
  settings["hooks"] = hooks;
2191
2243
  writeFileSync3(settingsPath, JSON.stringify(settings, null, 2));
2192
2244
  }
2245
+ function provisionIsolationHook(codeName) {
2246
+ const projectDir = getProjectDir(codeName);
2247
+ const claudeDir = join3(projectDir, ".claude");
2248
+ mkdirSync3(claudeDir, { recursive: true });
2249
+ const homeDir = getHomeDir3();
2250
+ const augmentedBase = join3(homeDir, ".augmented");
2251
+ const ownAgentDir = join3(augmentedBase, codeName);
2252
+ const logFile = join3(ownAgentDir, "isolation.log");
2253
+ const hookScriptPath = join3(claudeDir, "agt-isolation-hook.sh");
2254
+ const hookScript = [
2255
+ "#!/bin/bash",
2256
+ "# Auto-generated by Augmented \u2014 prevents cross-agent file access.",
2257
+ "# Exit 0 = allow, Exit 2 = block (with stderr message shown to agent)",
2258
+ "set -euo pipefail",
2259
+ "INPUT=$(cat)",
2260
+ `TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')`,
2261
+ "",
2262
+ "# Only check file-access tools",
2263
+ 'case "$TOOL" in',
2264
+ " Read|Edit|Write|Glob|Grep|MultiEdit) ;;",
2265
+ " Bash)",
2266
+ " # For Bash, we can't reliably parse arbitrary commands \u2014 rely on allowedDirectories.",
2267
+ " # But block obvious attempts to read other agent dirs.",
2268
+ ` CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')`,
2269
+ ` if echo "$CMD" | grep -qE '${augmentedBase}/[^/]+/' 2>/dev/null; then`,
2270
+ ` MATCH=$(echo "$CMD" | grep -oE '${augmentedBase}/[^/]+' | head -1)`,
2271
+ ` AGENT_DIR=$(basename "$MATCH")`,
2272
+ ` if [ "$AGENT_DIR" != "${codeName}" ] && [ "$AGENT_DIR" != "_mcp" ]; then`,
2273
+ ` echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) BLOCKED bash targeting $MATCH" >> "${logFile}"`,
2274
+ ` echo "Access denied: you cannot access other agents' directories." >&2`,
2275
+ " exit 2",
2276
+ " fi",
2277
+ " fi",
2278
+ " exit 0 ;;",
2279
+ " *) exit 0 ;;",
2280
+ "esac",
2281
+ "",
2282
+ "# Extract file_path from tool input",
2283
+ `FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')`,
2284
+ '[ -z "$FILE_PATH" ] && exit 0',
2285
+ "",
2286
+ "# Resolve to absolute path",
2287
+ 'if [[ "$FILE_PATH" != /* ]]; then',
2288
+ ` CWD=$(echo "$INPUT" | jq -r '.cwd // empty')`,
2289
+ ' [ -n "$CWD" ] && FILE_PATH="$CWD/$FILE_PATH"',
2290
+ "fi",
2291
+ "",
2292
+ "# Check if path targets another agent's directory",
2293
+ `AUGMENTED_BASE="${augmentedBase}"`,
2294
+ 'case "$FILE_PATH" in',
2295
+ ' "$AUGMENTED_BASE"/*/*) ',
2296
+ ' AGENT_DIR=$(echo "$FILE_PATH" | sed "s|$AUGMENTED_BASE/||" | cut -d/ -f1)',
2297
+ ` if [ "$AGENT_DIR" != "${codeName}" ] && [ "$AGENT_DIR" != "_mcp" ]; then`,
2298
+ ` echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) BLOCKED $TOOL on $FILE_PATH" >> "${logFile}"`,
2299
+ ` echo "Access denied: you cannot access other agents' directories." >&2`,
2300
+ " exit 2",
2301
+ " fi ;;",
2302
+ "esac",
2303
+ "",
2304
+ "exit 0"
2305
+ ].join("\n") + "\n";
2306
+ writeFileSync3(hookScriptPath, hookScript, { mode: 493 });
2307
+ const settingsPath = join3(claudeDir, "settings.local.json");
2308
+ let settings = {};
2309
+ try {
2310
+ settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
2311
+ } catch {
2312
+ }
2313
+ const hooks = settings["hooks"] ?? {};
2314
+ hooks["PreToolUse"] = [
2315
+ {
2316
+ hooks: [
2317
+ {
2318
+ type: "command",
2319
+ command: hookScriptPath
2320
+ }
2321
+ ]
2322
+ }
2323
+ ];
2324
+ settings["hooks"] = hooks;
2325
+ writeFileSync3(settingsPath, JSON.stringify(settings, null, 2));
2326
+ }
2193
2327
  function modifyJsonConfig(filePath, fn) {
2194
2328
  let originalContent;
2195
2329
  let config;
@@ -2225,6 +2359,19 @@ function buildSettingsJson(input) {
2225
2359
  if (agent.primary_model) {
2226
2360
  settings["model"] = agent.primary_model;
2227
2361
  }
2362
+ const projectDir = getProjectDir(agent.code_name);
2363
+ const agentDir = getAgentDir(agent.code_name);
2364
+ const homeDir = getHomeDir3();
2365
+ settings["allowedDirectories"] = [
2366
+ projectDir,
2367
+ // Agent's project dir (CLAUDE.md, settings.json, etc.)
2368
+ agentDir,
2369
+ // Agent's config dir (.env, schedules, registration)
2370
+ join3(homeDir, ".augmented", "_mcp"),
2371
+ // Shared MCP binaries
2372
+ "/tmp"
2373
+ // Temp files
2374
+ ];
2228
2375
  return settings;
2229
2376
  }
2230
2377
  function buildMcpJson(input) {
@@ -2425,9 +2572,9 @@ ${entry.content}`
2425
2572
  // so ensureGatewayRunning() returns early with running=false
2426
2573
  async getVersion() {
2427
2574
  try {
2428
- const { execFile: execFile3 } = await import("child_process");
2575
+ const { execFile: execFile4 } = await import("child_process");
2429
2576
  return new Promise((resolve3) => {
2430
- execFile3("claude", ["--version"], { timeout: 5e3 }, (err, stdout) => {
2577
+ execFile4("claude", ["--version"], { timeout: 5e3 }, (err, stdout) => {
2431
2578
  if (err) {
2432
2579
  resolve3(null);
2433
2580
  return;
@@ -2675,6 +2822,23 @@ ${entry.content}`
2675
2822
  args: ["-y", "@composio/mcp", "start", "--url", config.url],
2676
2823
  env: config.headers ?? {}
2677
2824
  };
2825
+ } else if (config.url.includes("mcp.pipedream.net")) {
2826
+ const pdUrl = new URL(config.url);
2827
+ const pathParts = pdUrl.pathname.split("/").filter(Boolean);
2828
+ const externalUserId = decodeURIComponent(pathParts[0] ?? "");
2829
+ const appSlug = decodeURIComponent(pathParts[1] ?? "");
2830
+ const headers = config.headers ?? {};
2831
+ const authToken = (headers["Authorization"] ?? "").replace("Bearer ", "");
2832
+ serverEntry = {
2833
+ command: "npx",
2834
+ args: ["-y", "@pipedream/mcp", "stdio", "--app", appSlug, "--external-user-id", externalUserId],
2835
+ env: {
2836
+ PIPEDREAM_PROJECT_ID: headers["x-pd-project-id"] ?? process.env["PIPEDREAM_PROJECT_ID"] ?? "",
2837
+ PIPEDREAM_CLIENT_ID: headers["x-pd-client-id"] ?? process.env["PIPEDREAM_CLIENT_ID"] ?? "",
2838
+ PIPEDREAM_CLIENT_SECRET: headers["x-pd-client-secret"] ?? process.env["PIPEDREAM_CLIENT_SECRET"] ?? "",
2839
+ PIPEDREAM_PROJECT_ENVIRONMENT: headers["x-pd-environment"] ?? process.env["PIPEDREAM_ENVIRONMENT"] ?? "development"
2840
+ }
2841
+ };
2678
2842
  } else {
2679
2843
  serverEntry = {
2680
2844
  command: "npx",
@@ -2748,6 +2912,40 @@ ${entry.content}`
2748
2912
  };
2749
2913
  writeFileSync3(pluginsJsonPath, JSON.stringify(pluginsConfig, null, 2));
2750
2914
  },
2915
+ executePluginHook(ctx) {
2916
+ assertValidCodeName(ctx.codeName);
2917
+ const agentRootDir = join3(getHomeDir3(), ".augmented", ctx.codeName);
2918
+ const projectDir = getProjectDir(ctx.codeName);
2919
+ mkdirSync3(agentRootDir, { recursive: true });
2920
+ mkdirSync3(projectDir, { recursive: true });
2921
+ const startedAt = Date.now();
2922
+ return new Promise((resolve3) => {
2923
+ const child = execFile3("bash", ["-c", ctx.script], {
2924
+ cwd: agentRootDir,
2925
+ timeout: 6e4,
2926
+ maxBuffer: 1024 * 1024,
2927
+ env: {
2928
+ ...process.env,
2929
+ AGENT_CODE_NAME: ctx.codeName,
2930
+ AGENT_DIR: agentRootDir,
2931
+ AGENT_PROJECT_DIR: projectDir,
2932
+ AGENT_FRAMEWORK: "claude-code"
2933
+ }
2934
+ }, (error, stdout, stderr) => {
2935
+ const durationMs = Date.now() - startedAt;
2936
+ const timedOut = !!error && error.code === "ETIMEDOUT";
2937
+ resolve3({
2938
+ exitCode: error ? typeof error.code === "number" ? error.code : 1 : 0,
2939
+ stdout: stdout?.toString() ?? "",
2940
+ stderr: stderr?.toString() ?? "",
2941
+ durationMs,
2942
+ timedOut
2943
+ });
2944
+ });
2945
+ child.on("error", () => {
2946
+ });
2947
+ });
2948
+ },
2751
2949
  writeTokenFile(codeName, integrations) {
2752
2950
  const agentDir = getAgentDir(codeName);
2753
2951
  mkdirSync3(agentDir, { recursive: true });
@@ -2888,6 +3086,11 @@ async function doExchange(rawKey, retried) {
2888
3086
  if (!res.ok) {
2889
3087
  const body = await res.json().catch(() => ({}));
2890
3088
  const errorMsg = String(body["error"] ?? res.statusText);
3089
+ const host = requireHost();
3090
+ const obfuscated = rawKey.length > 12 ? `${rawKey.slice(0, 8)}${"*".repeat(rawKey.length - 12)}${rawKey.slice(-4)}` : rawKey.slice(0, 4) + "****";
3091
+ if (res.status >= 502 && res.status <= 504) {
3092
+ throw new Error(`API unreachable (${res.status}): ${host} \u2014 is the API server running?`);
3093
+ }
2891
3094
  if (errorMsg.includes("revoked") && !retried) {
2892
3095
  reloadFromShellProfile();
2893
3096
  const freshKey = getApiKey();
@@ -2895,8 +3098,6 @@ async function doExchange(rawKey, retried) {
2895
3098
  return doExchange(freshKey, true);
2896
3099
  }
2897
3100
  }
2898
- const host = requireHost();
2899
- const obfuscated = rawKey.length > 12 ? `${rawKey.slice(0, 8)}${"*".repeat(rawKey.length - 12)}${rawKey.slice(-4)}` : rawKey.slice(0, 4) + "****";
2900
3101
  throw new Error(`API key exchange failed: ${errorMsg} (host=${host}, key=${obfuscated})`);
2901
3102
  }
2902
3103
  const data = await res.json();
@@ -4546,7 +4747,12 @@ var ROLE_PERMISSIONS = {
4546
4747
  "audit_log.view",
4547
4748
  "host.create",
4548
4749
  "host.manage",
4549
- "host.view"
4750
+ "host.view",
4751
+ "plugin.view",
4752
+ "plugin.install",
4753
+ "plugin.configure",
4754
+ "plugin.manage_scopes",
4755
+ "plugin.approve_requests"
4550
4756
  ],
4551
4757
  admin: [
4552
4758
  "team.manage_members",
@@ -4560,7 +4766,12 @@ var ROLE_PERMISSIONS = {
4560
4766
  "audit_log.view",
4561
4767
  "host.create",
4562
4768
  "host.manage",
4563
- "host.view"
4769
+ "host.view",
4770
+ "plugin.view",
4771
+ "plugin.install",
4772
+ "plugin.configure",
4773
+ "plugin.manage_scopes",
4774
+ "plugin.approve_requests"
4564
4775
  ],
4565
4776
  member: [
4566
4777
  "agent.create",
@@ -4568,12 +4779,15 @@ var ROLE_PERMISSIONS = {
4568
4779
  "agent.deploy",
4569
4780
  "agent.view",
4570
4781
  "audit_log.view",
4571
- "host.view"
4782
+ "host.view",
4783
+ "plugin.install",
4784
+ "plugin.view"
4572
4785
  ],
4573
4786
  viewer: [
4574
4787
  "agent.view",
4575
4788
  "audit_log.view",
4576
- "host.view"
4789
+ "host.view",
4790
+ "plugin.view"
4577
4791
  ]
4578
4792
  };
4579
4793
  var permissionSets = new Map(Object.entries(ROLE_PERMISSIONS).map(([role, actions]) => [role, new Set(actions)]));
@@ -4680,6 +4894,129 @@ function getTemplate(id) {
4680
4894
  return DEPLOYMENT_TEMPLATES.find((t) => t.id === id);
4681
4895
  }
4682
4896
 
4897
+ // ../../packages/core/dist/plugins/context-validator.js
4898
+ import Ajv20202 from "ajv/dist/2020.js";
4899
+ import addFormats2 from "ajv-formats";
4900
+
4901
+ // ../../packages/core/dist/plugins/context-meta-schema.json
4902
+ var context_meta_schema_default = {
4903
+ $schema: "https://json-schema.org/draft/2020-12/schema",
4904
+ $id: "https://augmented.dev/schemas/plugin-context.meta.schema.json",
4905
+ title: "Plugin Context Schema (meta)",
4906
+ description: "Meta-schema for the constrained subset of JSON Schema that plugin authors may declare for their plugin context. Anything outside this subset is rejected at PUT time. See ENG-4341 / docs/plugins/plugin-context-rfc.md.",
4907
+ type: "object",
4908
+ required: ["type", "properties"],
4909
+ additionalProperties: false,
4910
+ properties: {
4911
+ $schema: {
4912
+ type: "string"
4913
+ },
4914
+ type: {
4915
+ type: "string",
4916
+ const: "object"
4917
+ },
4918
+ properties: {
4919
+ type: "object",
4920
+ minProperties: 0,
4921
+ additionalProperties: {
4922
+ $ref: "#/$defs/field"
4923
+ }
4924
+ },
4925
+ required: {
4926
+ type: "array",
4927
+ items: { type: "string" },
4928
+ uniqueItems: true
4929
+ }
4930
+ },
4931
+ $defs: {
4932
+ field: {
4933
+ oneOf: [
4934
+ { $ref: "#/$defs/stringField" },
4935
+ { $ref: "#/$defs/booleanField" },
4936
+ { $ref: "#/$defs/stringArrayField" },
4937
+ { $ref: "#/$defs/stringMapField" }
4938
+ ]
4939
+ },
4940
+ stringField: {
4941
+ type: "object",
4942
+ required: ["type"],
4943
+ additionalProperties: false,
4944
+ properties: {
4945
+ type: { const: "string" },
4946
+ title: { type: "string" },
4947
+ description: { type: "string" },
4948
+ enum: {
4949
+ type: "array",
4950
+ items: { type: "string" },
4951
+ minItems: 1,
4952
+ uniqueItems: true
4953
+ },
4954
+ default: { type: "string" }
4955
+ }
4956
+ },
4957
+ booleanField: {
4958
+ type: "object",
4959
+ required: ["type"],
4960
+ additionalProperties: false,
4961
+ properties: {
4962
+ type: { const: "boolean" },
4963
+ title: { type: "string" },
4964
+ description: { type: "string" },
4965
+ default: { type: "boolean" }
4966
+ }
4967
+ },
4968
+ stringArrayField: {
4969
+ type: "object",
4970
+ required: ["type", "items"],
4971
+ additionalProperties: false,
4972
+ properties: {
4973
+ type: { const: "array" },
4974
+ items: {
4975
+ type: "object",
4976
+ required: ["type"],
4977
+ additionalProperties: false,
4978
+ properties: {
4979
+ type: { const: "string" }
4980
+ }
4981
+ },
4982
+ title: { type: "string" },
4983
+ description: { type: "string" },
4984
+ default: {
4985
+ type: "array",
4986
+ items: { type: "string" }
4987
+ }
4988
+ }
4989
+ },
4990
+ stringMapField: {
4991
+ type: "object",
4992
+ required: ["type", "additionalProperties"],
4993
+ additionalProperties: false,
4994
+ properties: {
4995
+ type: { const: "object" },
4996
+ additionalProperties: {
4997
+ type: "object",
4998
+ required: ["type"],
4999
+ additionalProperties: false,
5000
+ properties: {
5001
+ type: { const: "string" }
5002
+ }
5003
+ },
5004
+ title: { type: "string" },
5005
+ description: { type: "string" },
5006
+ default: {
5007
+ type: "object",
5008
+ additionalProperties: { type: "string" }
5009
+ }
5010
+ }
5011
+ }
5012
+ }
5013
+ };
5014
+
5015
+ // ../../packages/core/dist/plugins/context-validator.js
5016
+ var ajv2 = new Ajv20202({ allErrors: true, strict: false });
5017
+ addFormats2(ajv2);
5018
+ var compiledMetaSchema = ajv2.compile(context_meta_schema_default);
5019
+
4683
5020
  // ../../packages/core/dist/drift/comparators.js
4684
5021
  function compareToolPolicy(expected, actual) {
4685
5022
  const findings = [];
@@ -4876,6 +5213,7 @@ export {
4876
5213
  getChannel,
4877
5214
  getAllChannelIds,
4878
5215
  provisionStopHook,
5216
+ provisionIsolationHook,
4879
5217
  getApiKey,
4880
5218
  getActiveTeam,
4881
5219
  setActiveTeam,
@@ -4906,4 +5244,4 @@ export {
4906
5244
  detectDrift,
4907
5245
  provision
4908
5246
  };
4909
- //# sourceMappingURL=chunk-N7TRKQMT.js.map
5247
+ //# sourceMappingURL=chunk-VCKY6MN2.js.map