@botbotgo/runtime 1.0.1 → 1.0.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.
Files changed (83) hide show
  1. package/.github/workflows/release.yml +63 -0
  2. package/config/examples/runtime.yaml +14 -0
  3. package/config/examples/tool.yaml +1 -1
  4. package/dist/config/resolveRuntimeConfig.d.ts +3 -1
  5. package/dist/config/resolveRuntimeConfig.d.ts.map +1 -1
  6. package/dist/config/resolveRuntimeConfig.js +2 -0
  7. package/dist/config/resolveRuntimeConfig.js.map +1 -1
  8. package/dist/config/resources.d.ts +17 -0
  9. package/dist/config/resources.d.ts.map +1 -1
  10. package/dist/config/resources.js.map +1 -1
  11. package/dist/runtime/bootstrap/runtimeFactory.d.ts.map +1 -1
  12. package/dist/runtime/bootstrap/runtimeFactory.js +4 -0
  13. package/dist/runtime/bootstrap/runtimeFactory.js.map +1 -1
  14. package/dist/runtime/execution/agentRunExecutor.d.ts +1 -0
  15. package/dist/runtime/execution/agentRunExecutor.d.ts.map +1 -1
  16. package/dist/runtime/execution/agentRunExecutor.js +3 -0
  17. package/dist/runtime/execution/agentRunExecutor.js.map +1 -1
  18. package/dist/runtime/execution/agentRunExecutor.types.d.ts +2 -0
  19. package/dist/runtime/execution/agentRunExecutor.types.d.ts.map +1 -1
  20. package/dist/runtime/middleware/agentToolMiddleware.d.ts +2 -0
  21. package/dist/runtime/middleware/agentToolMiddleware.d.ts.map +1 -1
  22. package/dist/runtime/middleware/agentToolMiddleware.js +17 -4
  23. package/dist/runtime/middleware/agentToolMiddleware.js.map +1 -1
  24. package/dist/runtime/middleware/commandPolicy.d.ts +2 -1
  25. package/dist/runtime/middleware/commandPolicy.d.ts.map +1 -1
  26. package/dist/runtime/middleware/commandPolicy.js +14 -11
  27. package/dist/runtime/middleware/commandPolicy.js.map +1 -1
  28. package/dist/runtime/middleware/frameworkPrompt.d.ts.map +1 -1
  29. package/dist/runtime/middleware/frameworkPrompt.js +2 -3
  30. package/dist/runtime/middleware/frameworkPrompt.js.map +1 -1
  31. package/dist/runtime/middleware/toolArgsNormalizer.d.ts +1 -0
  32. package/dist/runtime/middleware/toolArgsNormalizer.d.ts.map +1 -1
  33. package/dist/runtime/middleware/toolArgsNormalizer.js +32 -0
  34. package/dist/runtime/middleware/toolArgsNormalizer.js.map +1 -1
  35. package/dist/runtime/middleware/toolCallGuard.d.ts +3 -1
  36. package/dist/runtime/middleware/toolCallGuard.d.ts.map +1 -1
  37. package/dist/runtime/middleware/toolCallGuard.js +24 -4
  38. package/dist/runtime/middleware/toolCallGuard.js.map +1 -1
  39. package/dist/runtime/middleware/types.d.ts +2 -0
  40. package/dist/runtime/middleware/types.d.ts.map +1 -1
  41. package/dist/runtime/middleware/types.js.map +1 -1
  42. package/dist/runtime/runtimeService.d.ts +2 -0
  43. package/dist/runtime/runtimeService.d.ts.map +1 -1
  44. package/dist/runtime/runtimeService.js +1 -0
  45. package/dist/runtime/runtimeService.js.map +1 -1
  46. package/dist/runtime/stream/runArtifacts.d.ts.map +1 -1
  47. package/dist/runtime/stream/runArtifacts.js +3 -1
  48. package/dist/runtime/stream/runArtifacts.js.map +1 -1
  49. package/dist/state/runState.d.ts +1 -0
  50. package/dist/state/runState.d.ts.map +1 -1
  51. package/dist/state/runState.js +18 -1
  52. package/dist/state/runState.js.map +1 -1
  53. package/dist/state/workspaceState.d.ts +2 -0
  54. package/dist/state/workspaceState.d.ts.map +1 -1
  55. package/dist/state/workspaceState.js +12 -10
  56. package/dist/state/workspaceState.js.map +1 -1
  57. package/example/config/model.yaml +2 -2
  58. package/example/config/runtime.yaml +19 -1
  59. package/example/package.json +0 -1
  60. package/package.json +1 -1
  61. package/src/config/resolveRuntimeConfig.ts +5 -0
  62. package/src/config/resources.ts +19 -0
  63. package/src/runtime/bootstrap/runtimeFactory.ts +7 -0
  64. package/src/runtime/execution/agentRunExecutor.ts +3 -0
  65. package/src/runtime/execution/agentRunExecutor.types.ts +2 -0
  66. package/src/runtime/middleware/agentToolMiddleware.ts +19 -3
  67. package/src/runtime/middleware/commandPolicy.ts +22 -10
  68. package/src/runtime/middleware/frameworkPrompt.ts +2 -3
  69. package/src/runtime/middleware/toolArgsNormalizer.ts +36 -0
  70. package/src/runtime/middleware/toolCallGuard.ts +37 -3
  71. package/src/runtime/middleware/types.ts +2 -0
  72. package/src/runtime/runtimeService.ts +3 -0
  73. package/src/runtime/stream/runArtifacts.ts +3 -1
  74. package/src/state/runState.ts +19 -1
  75. package/src/state/workspaceState.ts +19 -11
  76. package/test/unit/config/loader.test.ts +10 -0
  77. package/test/unit/runtime/agentToolMiddleware.test.ts +51 -0
  78. package/test/unit/runtime/toolArgsNormalizer.test.ts +34 -0
  79. package/test/unit/runtime/toolCallGuard.test.ts +71 -0
  80. package/test/unit/runtime/workspaceState.test.ts +94 -0
  81. package/example/.tsbuildinfo +0 -1
  82. package/example/build/.tsbuildinfo +0 -1
  83. package/example/serve-output.mjs +0 -52
@@ -1 +1 @@
1
- {"version":3,"file":"workspaceState.js","sourceRoot":"","sources":["../../src/state/workspaceState.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspaceState.js","sourceRoot":"","sources":["../../src/state/workspaceState.ts"],"names":[],"mappings":"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"}
@@ -7,8 +7,8 @@ spec:
7
7
  default: gpt_oss
8
8
  gpt_oss:
9
9
  provider: openai
10
- base_url: https://ollama-rtx-4070.botbotgo.world/v1
10
+ base_url: https://ollama-rtx-4070.easynet.world/v1
11
11
  model: gpt-oss:latest
12
12
  apiKey: ollama
13
13
  options:
14
- timeoutMs: 70000
14
+ timeoutMs: 300000
@@ -10,6 +10,10 @@ spec:
10
10
  - key: companyReportHtml
11
11
  path: output/company-report.html
12
12
 
13
+ # Resume interrupted runs by default so repeated invocations can continue
14
+ # from .agent/run-state.json instead of restarting from scratch.
15
+ resumeInterruptedRun: true
16
+
13
17
  # Workspace state persisted under the example root.
14
18
  stateDirName: .agent
15
19
  legacyOutputState: true
@@ -23,7 +27,7 @@ spec:
23
27
 
24
28
  # Execution limits tuned for a skill-driven report run.
25
29
  executeTimeoutMs: 60000
26
- llmIdleTimeoutMs: 70000
30
+ llmIdleTimeoutMs: 300000
27
31
  heartbeatIntervalMs: 5000
28
32
  backend:
29
33
  type: local_shell
@@ -36,6 +40,20 @@ spec:
36
40
  malformedToolCallMaxRetries: 0
37
41
  idleTimeoutMaxRetries: 1
38
42
 
43
+ # Middleware guardrails can be tuned here without code changes.
44
+ middleware:
45
+ forbidScriptSourceRead: true
46
+ forbidAbsolutePathsOutsideWorkspace: true
47
+ commandPolicy:
48
+ blockFuzzyLsProbes: true
49
+ blockShellWrappedSkillScripts: true
50
+ blockChmodX: true
51
+ blockShellDashLc: true
52
+ blockDirectNetworkFetch: true
53
+ blockReportgenPipe: true
54
+ blockShellFileRedirection: true
55
+ blockAbsolutePathsOutsideWorkspace: true
56
+
39
57
  # Fine-grained event toggles. Prefer this over eventLogLevel when you need
40
58
  # explicit control over which runtime events are printed.
41
59
  debug:
@@ -8,7 +8,6 @@
8
8
  "build": "tsc --incremental --tsBuildInfoFile .tsbuildinfo",
9
9
  "start": "node --import tsx index.ts",
10
10
  "start:prod": "npm --prefix .. run build && npm run build && node dist/index.js",
11
- "report:serve": "node serve-output.mjs",
12
11
  "dev": "tsx index.ts",
13
12
  "test": "npm run build"
14
13
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/runtime",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Runtime service and YAML config loader for deepagents-based agent apps",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -7,6 +7,7 @@
7
7
  import type {
8
8
  AgentBackendConfigSpec,
9
9
  AgentRuntimeConfigResource,
10
+ AgentRuntimeMiddlewareSpec,
10
11
  KnownResource,
11
12
  MemoryConfigResource,
12
13
  } from "./resources.js";
@@ -48,6 +49,7 @@ export interface ResolvedAgentRuntimeConfig {
48
49
  key: string;
49
50
  path: string;
50
51
  }>;
52
+ resumeInterruptedRun?: boolean;
51
53
  stateDirName?: string;
52
54
  legacyOutputState?: boolean;
53
55
  executeTimeoutMs?: number;
@@ -60,6 +62,7 @@ export interface ResolvedAgentRuntimeConfig {
60
62
  malformedToolCallMaxRetries?: number;
61
63
  idleTimeoutMaxRetries?: number;
62
64
  heartbeatIntervalMs?: number;
65
+ middleware?: AgentRuntimeMiddlewareSpec;
63
66
  debug?: {
64
67
  run?: boolean;
65
68
  workspace?: boolean;
@@ -127,6 +130,7 @@ function resolveStore(s: MemoryConfigResource["spec"]["memory"]["thread"]): Memo
127
130
  function resolveRuntime(s: AgentRuntimeConfigResource["spec"]): ResolvedAgentRuntimeConfig {
128
131
  return {
129
132
  artifacts: s.artifacts,
133
+ resumeInterruptedRun: s.resumeInterruptedRun,
130
134
  stateDirName: s.stateDirName,
131
135
  legacyOutputState: s.legacyOutputState,
132
136
  executeTimeoutMs: s.executeTimeoutMs,
@@ -139,6 +143,7 @@ function resolveRuntime(s: AgentRuntimeConfigResource["spec"]): ResolvedAgentRun
139
143
  malformedToolCallMaxRetries: s.malformedToolCallMaxRetries,
140
144
  idleTimeoutMaxRetries: s.idleTimeoutMaxRetries,
141
145
  heartbeatIntervalMs: s.heartbeatIntervalMs,
146
+ middleware: s.middleware,
142
147
  debug: s.debug,
143
148
  eventLogLevel: s.eventLogLevel,
144
149
  };
@@ -95,11 +95,29 @@ export interface AgentBackendConfigSpec {
95
95
  maxOutputBytes?: number;
96
96
  }
97
97
 
98
+ export interface AgentRuntimeCommandPolicySpec {
99
+ blockFuzzyLsProbes?: boolean;
100
+ blockShellWrappedSkillScripts?: boolean;
101
+ blockChmodX?: boolean;
102
+ blockShellDashLc?: boolean;
103
+ blockDirectNetworkFetch?: boolean;
104
+ blockReportgenPipe?: boolean;
105
+ blockShellFileRedirection?: boolean;
106
+ blockAbsolutePathsOutsideWorkspace?: boolean;
107
+ }
108
+
109
+ export interface AgentRuntimeMiddlewareSpec {
110
+ forbidScriptSourceRead?: boolean;
111
+ forbidAbsolutePathsOutsideWorkspace?: boolean;
112
+ commandPolicy?: AgentRuntimeCommandPolicySpec;
113
+ }
114
+
98
115
  export interface AgentRuntimeConfigSpec {
99
116
  artifacts?: Array<{
100
117
  key: string;
101
118
  path: string;
102
119
  }>;
120
+ resumeInterruptedRun?: boolean;
103
121
  stateDirName?: string;
104
122
  legacyOutputState?: boolean;
105
123
  executeTimeoutMs?: number;
@@ -112,6 +130,7 @@ export interface AgentRuntimeConfigSpec {
112
130
  malformedToolCallMaxRetries?: number;
113
131
  idleTimeoutMaxRetries?: number;
114
132
  heartbeatIntervalMs?: number;
133
+ middleware?: AgentRuntimeMiddlewareSpec;
115
134
  debug?: {
116
135
  run?: boolean;
117
136
  workspace?: boolean;
@@ -69,6 +69,7 @@ export class AgentRuntimeFactory {
69
69
  defaultEmptyRunMaxRetries: runtimeDeps.defaultEmptyRunMaxRetries,
70
70
  defaultMalformedToolCallMaxRetries: runtimeDeps.defaultMalformedToolCallMaxRetries,
71
71
  defaultIdleTimeoutMaxRetries: runtimeDeps.defaultIdleTimeoutMaxRetries,
72
+ defaultResumeInterruptedRun: runtimeDeps.defaultResumeInterruptedRun,
72
73
  defaultHeartbeatIntervalMs: runtimeDeps.defaultHeartbeatIntervalMs,
73
74
  defaultIdleTimeoutMs: runtimeDeps.defaultIdleTimeoutMs,
74
75
  artifactValidator: runtimeDeps.artifactValidator,
@@ -109,6 +110,7 @@ export class AgentRuntimeFactory {
109
110
  executeTimeoutMs: runtimeDeps.executeTimeoutMs,
110
111
  blockTaskTool: runtimeDeps.blockTaskTool,
111
112
  allowedToolNames: runtimeDeps.allowedToolNames,
113
+ policy: runtimeDeps.middleware,
112
114
  logger: runtimeDeps.logger,
113
115
  persistTodos: workspace.persistTodos.bind(workspace),
114
116
  humanLoop: runtimeDeps.humanLoop,
@@ -170,10 +172,13 @@ class RuntimeOptionsResolver {
170
172
  this.options.malformedToolCallMaxRetries ?? runtimeConfig.malformedToolCallMaxRetries,
171
173
  defaultIdleTimeoutMaxRetries:
172
174
  this.options.idleTimeoutMaxRetries ?? runtimeConfig.idleTimeoutMaxRetries,
175
+ defaultResumeInterruptedRun:
176
+ this.options.resumeInterruptedRun ?? runtimeConfig.resumeInterruptedRun,
173
177
  defaultHeartbeatIntervalMs:
174
178
  this.options.heartbeatIntervalMs ?? runtimeConfig.heartbeatIntervalMs,
175
179
  defaultIdleTimeoutMs:
176
180
  this.options.idleTimeoutMs ?? runtimeConfig.llmIdleTimeoutMs,
181
+ middleware: runtimeConfig.middleware,
177
182
  };
178
183
  }
179
184
 
@@ -207,6 +212,8 @@ interface ResolvedRuntimeOptions {
207
212
  defaultEmptyRunMaxRetries: number | undefined;
208
213
  defaultMalformedToolCallMaxRetries: number | undefined;
209
214
  defaultIdleTimeoutMaxRetries: number | undefined;
215
+ defaultResumeInterruptedRun: boolean | undefined;
210
216
  defaultHeartbeatIntervalMs: number | undefined;
211
217
  defaultIdleTimeoutMs: number | undefined;
218
+ middleware: ResolvedAgentRuntimeConfig["middleware"];
212
219
  }
@@ -22,6 +22,7 @@ export class AgentRunExecutor {
22
22
  private readonly defaultEmptyRunMaxRetries?: number;
23
23
  private readonly defaultMalformedToolCallMaxRetries?: number;
24
24
  private readonly defaultIdleTimeoutMaxRetries?: number;
25
+ private readonly defaultResumeInterruptedRun?: boolean;
25
26
  private readonly defaultHeartbeatIntervalMs?: number;
26
27
  private readonly defaultIdleTimeoutMs?: number;
27
28
  private readonly artifactValidator?: ConstructorParams["artifactValidator"];
@@ -35,6 +36,7 @@ export class AgentRunExecutor {
35
36
  this.defaultEmptyRunMaxRetries = params.defaultEmptyRunMaxRetries;
36
37
  this.defaultMalformedToolCallMaxRetries = params.defaultMalformedToolCallMaxRetries;
37
38
  this.defaultIdleTimeoutMaxRetries = params.defaultIdleTimeoutMaxRetries;
39
+ this.defaultResumeInterruptedRun = params.defaultResumeInterruptedRun;
38
40
  this.defaultHeartbeatIntervalMs = params.defaultHeartbeatIntervalMs;
39
41
  this.defaultIdleTimeoutMs = params.defaultIdleTimeoutMs;
40
42
  this.artifactValidator = params.artifactValidator;
@@ -91,6 +93,7 @@ export class AgentRunExecutor {
91
93
 
92
94
  const run = await this.workspace.prepareRun({
93
95
  prompt: effectivePrompt,
96
+ resumeInterruptedRun: params.resumeInterruptedRun ?? this.defaultResumeInterruptedRun ?? true,
94
97
  fallbackThreadId: params.fallbackThreadId,
95
98
  resumeHint:
96
99
  params.resumeHint ??
@@ -2,6 +2,7 @@ import type { DrainAgentStreamOptions } from "../stream/agentStream.js";
2
2
  import type { AgentWorkspaceState } from "../../state/workspaceState.js";
3
3
 
4
4
  export interface AgentRuntimeRunOptions<TChunk> {
5
+ resumeInterruptedRun?: boolean;
5
6
  resumeHint?: string;
6
7
  fallbackThreadId?: string;
7
8
  malformedToolCallMaxRetries?: number;
@@ -28,6 +29,7 @@ export interface ConstructorParams {
28
29
  defaultEmptyRunMaxRetries?: number;
29
30
  defaultMalformedToolCallMaxRetries?: number;
30
31
  defaultIdleTimeoutMaxRetries?: number;
32
+ defaultResumeInterruptedRun?: boolean;
31
33
  defaultHeartbeatIntervalMs?: number;
32
34
  defaultIdleTimeoutMs?: number;
33
35
  artifactValidator?: AgentRuntimeRunOptions<unknown>["artifactValidator"];
@@ -11,6 +11,7 @@ import type {
11
11
  CreateAgentToolMiddlewareOptions,
12
12
  ToolArgs,
13
13
  } from "./types.js";
14
+ import type { AgentRuntimeMiddlewareSpec } from "../../config/resources.js";
14
15
 
15
16
  export class AgentToolMiddlewareFactory {
16
17
  private readonly rootDir: string;
@@ -22,6 +23,7 @@ export class AgentToolMiddlewareFactory {
22
23
  private readonly executeTimeoutMs: number;
23
24
  private readonly blockTaskTool: boolean;
24
25
  private readonly allowedToolNames?: string[];
26
+ private readonly policy?: AgentRuntimeMiddlewareSpec;
25
27
  private readonly logger: (message: string) => void;
26
28
  private readonly persistTodos?: (todos: unknown[]) => Promise<void> | void;
27
29
  private readonly humanLoop?: CreateAgentToolMiddlewareOptions["humanLoop"];
@@ -39,6 +41,7 @@ export class AgentToolMiddlewareFactory {
39
41
  this.executeTimeoutMs = options.executeTimeoutMs ?? 60_000;
40
42
  this.blockTaskTool = options.blockTaskTool ?? false;
41
43
  this.allowedToolNames = options.allowedToolNames?.filter((name) => typeof name === "string" && name.trim().length > 0);
44
+ this.policy = options.policy;
42
45
  this.logger = options.logger ?? (() => {});
43
46
  this.persistTodos = options.persistTodos;
44
47
  this.humanLoop = options.humanLoop;
@@ -74,14 +77,15 @@ export class AgentToolMiddlewareFactory {
74
77
  const toolCallId = toolRequest.toolCall.id;
75
78
 
76
79
  if (this.blockTaskTool && name === "task") {
80
+ const error = "Error: Do not use the task tool. Use execute(), write_file(), and read_file() directly.";
77
81
  this.events?.emit({
78
82
  name: "agent.runtime2.tool.call.blocked",
79
83
  from: "agent-runtime2.middleware",
80
84
  to: name,
81
- payload: { toolCallId, reason: "task_tool_disabled" },
85
+ payload: { toolCallId, reason: "task_tool_disabled", error },
82
86
  });
83
87
  return new this.ToolMessage({
84
- content: "Error: Do not use the task tool. Use execute(), write_file(), and read_file() directly.",
88
+ content: error,
85
89
  tool_call_id: toolCallId ?? "blocked",
86
90
  });
87
91
  }
@@ -95,13 +99,15 @@ export class AgentToolMiddlewareFactory {
95
99
  this.rootDir,
96
100
  this.allowedToolNames,
97
101
  Object.values(this.skillPathMap),
102
+ this.policy,
98
103
  );
99
104
  if (blocked) {
105
+ const error = this.extractToolMessageContent(blocked);
100
106
  this.events?.emit({
101
107
  name: "agent.runtime2.tool.call.blocked",
102
108
  from: "agent-runtime2.middleware",
103
109
  to: name,
104
- payload: { toolCallId, args, reason: "policy_violation" },
110
+ payload: { toolCallId, args, reason: "policy_violation", error },
105
111
  });
106
112
  return blocked;
107
113
  }
@@ -326,4 +332,14 @@ export class AgentToolMiddlewareFactory {
326
332
  }
327
333
  this.logger(`[tool] ${name}`);
328
334
  }
335
+
336
+ private extractToolMessageContent(value: unknown): string | undefined {
337
+ if (!value || typeof value !== "object") {
338
+ return undefined;
339
+ }
340
+ const candidate = value as { content?: unknown };
341
+ return typeof candidate.content === "string" && candidate.content.trim()
342
+ ? candidate.content.trim()
343
+ : undefined;
344
+ }
329
345
  }
@@ -1,3 +1,4 @@
1
+ import type { AgentRuntimeCommandPolicySpec } from "../../config/resources.js";
1
2
  import type { ToolMessageConstructorLike, ToolMessageLike } from "./types.js";
2
3
 
3
4
  export class CommandPolicy {
@@ -7,34 +8,45 @@ export class CommandPolicy {
7
8
  ToolMessage: ToolMessageConstructorLike,
8
9
  rootDir: string,
9
10
  allowedPathPrefixes: string[] = [],
11
+ policy?: AgentRuntimeCommandPolicySpec,
10
12
  ): ToolMessageLike | null {
11
- const message = this.getViolationMessage(command, rootDir, allowedPathPrefixes);
13
+ const message = this.getViolationMessage(command, rootDir, allowedPathPrefixes, policy);
12
14
  return message ? new ToolMessage({ content: message, tool_call_id: toolCallId ?? "execute" }) : null;
13
15
  }
14
16
 
15
- private static getViolationMessage(command: string, rootDir: string, allowedPathPrefixes: string[]): string | null {
16
- if (/\bls\b/.test(command) && command.includes("?")) {
17
+ private static getViolationMessage(
18
+ command: string,
19
+ rootDir: string,
20
+ allowedPathPrefixes: string[],
21
+ policy?: AgentRuntimeCommandPolicySpec,
22
+ ): string | null {
23
+ if (policy?.blockFuzzyLsProbes !== false && /\bls\b/.test(command) && command.includes("?")) {
17
24
  return "Error: Do not run fuzzy ls probes with unknown paths. Continue with known workflow commands.";
18
25
  }
19
- if ((/\bbash\b/i.test(command) || /\/bin\/bash\b/i.test(command) || /\bzsh\b/i.test(command)) && command.includes("/scripts/")) {
26
+ if (
27
+ policy?.blockShellWrappedSkillScripts !== false
28
+ && (/\bbash\b/i.test(command) || /\/bin\/bash\b/i.test(command) || /\bzsh\b/i.test(command))
29
+ && command.includes("/scripts/")
30
+ ) {
20
31
  return "Error: Do not wrap skill scripts with `bash`. Execute the script path directly.";
21
32
  }
22
- if (/\bchmod\s+\+x\b/i.test(command)) {
33
+ if (policy?.blockChmodX !== false && /\bchmod\s+\+x\b/i.test(command)) {
23
34
  return "Error: Do not run chmod +x. Use direct execution of the target command or script.";
24
35
  }
25
- if (/\b(?:ba)?sh\s+-lc\b/i.test(command)) {
36
+ if (policy?.blockShellDashLc !== false && /\b(?:ba)?sh\s+-lc\b/i.test(command)) {
26
37
  return "Error: Do not wrap command execution with shell -lc. Execute the target command directly.";
27
38
  }
28
- if (/\b(curl|wget)\b/i.test(command)) {
39
+ if (policy?.blockDirectNetworkFetch !== false && /\b(curl|wget)\b/i.test(command)) {
29
40
  return "Error: Do not execute direct network fetch commands. Use provided scripts/tools and then write results with write_file/edit_file.";
30
41
  }
31
- if (/\|\s*reportgen\b/i.test(command)) {
42
+ if (policy?.blockReportgenPipe !== false && /\|\s*reportgen\b/i.test(command)) {
32
43
  return "Error: Do not pipe output to ad-hoc generators. Use write_file/edit_file for artifact generation.";
33
44
  }
34
- if (/(^|[\s;|&])(?:echo|cat|printf)[^|&;]*>\s*[^\s]+/i.test(command)) {
45
+ if (policy?.blockShellFileRedirection !== false && /(^|[\s;|&])(?:echo|cat|printf)[^|&;]*>\s*[^\s]+/i.test(command)) {
35
46
  return "Error: Do not write files via shell redirection in execute. Use write_file/edit_file tools.";
36
47
  }
37
- return this.containsAbsolutePathOutsideWorkspace(command, rootDir, allowedPathPrefixes)
48
+ return (policy?.blockAbsolutePathsOutsideWorkspace !== false)
49
+ && this.containsAbsolutePathOutsideWorkspace(command, rootDir, allowedPathPrefixes)
38
50
  ? "Error: Do not execute commands with absolute paths outside workspace root. Use workspace-relative paths only."
39
51
  : null;
40
52
  }
@@ -37,9 +37,8 @@ export class FrameworkPrompt {
37
37
  if (skillEntries.length === 1) {
38
38
  baseRules.push("- Because only one skill is active, `${SKILL_PATH}` also resolves to that skill directory.");
39
39
  }
40
- baseRules.push("- `${SKILL_PATH...}` is only for skill-owned assets such as scripts/, references/, templates, and static inputs explicitly required by the SKILL.");
41
- baseRules.push("- Do not use `${SKILL_PATH...}` for exploration, listing, globbing, discovery, or inspection. Do not call ls/glob/read_file on a skill path unless the user explicitly asks for skill source or contents.");
42
- baseRules.push("- If a SKILL provides an explicit script command using `${SKILL_PATH...}` and `${WORKSPACE}`, execute that command directly instead of exploring the skill directory first.");
40
+ baseRules.push("- `${SKILL_PATH...}` is only for exact skill-owned files explicitly required by the active SKILL.");
41
+ baseRules.push("- If a SKILL provides an explicit script command using `${SKILL_PATH...}` and `${WORKSPACE}`, execute that command directly without exploring the skill directory.");
43
42
  }
44
43
 
45
44
  const frameworkPrompt = baseRules.join("\n");
@@ -72,6 +72,12 @@ export class ToolArgsNormalizer {
72
72
  for (const key of TOOL_PATH_ARG_KEYS) {
73
73
  const value = nextArgs[key];
74
74
  if (!this.shouldNormalizePath(value)) {
75
+ if (typeof value === "string") {
76
+ const normalizedRelative = this.normalizeWorkspaceRelativePath(rootDir, value);
77
+ if (normalizedRelative !== value) {
78
+ nextArgs = { ...nextArgs, [key]: normalizedRelative };
79
+ }
80
+ }
75
81
  continue;
76
82
  }
77
83
  if (this.isResolvableAbsolutePath(rootDir, value)) {
@@ -192,6 +198,10 @@ export class ToolArgsNormalizer {
192
198
  if (!this.looksLikeRelativePath(value) || value.startsWith("./") || value.startsWith("../")) {
193
199
  return value;
194
200
  }
201
+ const normalizedRelative = this.normalizeWorkspaceRelativePath(rootDir, value);
202
+ if (normalizedRelative !== value) {
203
+ return normalizedRelative;
204
+ }
195
205
  if (existsSync(resolve(rootDir, value))) {
196
206
  return value;
197
207
  }
@@ -211,6 +221,32 @@ export class ToolArgsNormalizer {
211
221
  return value.includes("/") && !value.startsWith("/") && !value.startsWith("~") && !value.startsWith("-");
212
222
  }
213
223
 
224
+ private static normalizeWorkspaceRelativePath(rootDir: string, value: string): string {
225
+ const normalizedValue = value.replace(/\\/g, "/").replace(/^\.\/+/, "");
226
+ if (!this.looksLikeRelativePath(normalizedValue)) {
227
+ return value;
228
+ }
229
+
230
+ const rootSegments = rootDir.replace(/\\/g, "/").split("/").filter(Boolean);
231
+ const valueSegments = normalizedValue.split("/").filter(Boolean);
232
+ if (valueSegments.length < 2 || rootSegments.length < 2) {
233
+ return value;
234
+ }
235
+
236
+ for (let index = 0; index <= rootSegments.length - 2; index += 1) {
237
+ const suffixSegments = rootSegments.slice(index);
238
+ if (valueSegments.length <= suffixSegments.length) {
239
+ continue;
240
+ }
241
+ const matches = suffixSegments.every((segment, suffixIndex) => valueSegments[suffixIndex] === segment);
242
+ if (matches) {
243
+ return valueSegments.slice(suffixSegments.length).join("/");
244
+ }
245
+ }
246
+
247
+ return value;
248
+ }
249
+
214
250
  private static quoteCommandPart(value: string): string {
215
251
  return /^[A-Za-z0-9_./:@=-]+$/.test(value)
216
252
  ? value
@@ -1,3 +1,4 @@
1
+ import type { AgentRuntimeMiddlewareSpec } from "../../config/resources.js";
1
2
  import { CommandPolicy } from "./commandPolicy.js";
2
3
  import { ToolArgsNormalizer } from "./toolArgsNormalizer.js";
3
4
  import { TOOL_PATH_ARG_KEYS, type ToolArgs, type ToolMessageConstructorLike, type ToolMessageLike } from "./types.js";
@@ -11,6 +12,7 @@ export class ToolCallGuard {
11
12
  rootDir: string,
12
13
  allowedToolNames?: string[],
13
14
  allowedPathPrefixes: string[] = [],
15
+ policy?: AgentRuntimeMiddlewareSpec,
14
16
  ): ToolMessageLike | null {
15
17
  if (allowedToolNames?.length && !this.isToolAllowed(name, allowedToolNames)) {
16
18
  return new ToolMessage({
@@ -18,20 +20,40 @@ export class ToolCallGuard {
18
20
  tool_call_id: toolCallId ?? name,
19
21
  });
20
22
  }
21
- if ((name === "read_file" || name === "edit_file") && this.isScriptSourcePath(args, rootDir)) {
23
+ if (
24
+ policy?.forbidScriptSourceRead !== false
25
+ && (name === "read_file" || name === "edit_file")
26
+ && this.isScriptSourcePath(args, rootDir)
27
+ ) {
22
28
  return new ToolMessage({
23
29
  content: "Error: Do not inspect script source files unless the user explicitly asks for script code.",
24
30
  tool_call_id: toolCallId ?? name,
25
31
  });
26
32
  }
27
- if (this.hasAbsolutePathArgOutsideWorkspace(args, rootDir, allowedPathPrefixes)) {
33
+ if ((name === "read_file" || name === "edit_file") && this.isInternalStatePath(args, rootDir)) {
34
+ return new ToolMessage({
35
+ content: "Error: Do not inspect internal runtime state files under .agent/. Follow the SKILL workflow instead.",
36
+ tool_call_id: toolCallId ?? name,
37
+ });
38
+ }
39
+ if (
40
+ policy?.forbidAbsolutePathsOutsideWorkspace !== false
41
+ && this.hasAbsolutePathArgOutsideWorkspace(args, rootDir, allowedPathPrefixes)
42
+ ) {
28
43
  return new ToolMessage({
29
44
  content: "Error: Do not use absolute filesystem paths outside workspace root. Use workspace-relative paths only.",
30
45
  tool_call_id: toolCallId ?? name,
31
46
  });
32
47
  }
33
48
  if (name === "execute" && typeof args.command === "string") {
34
- return CommandPolicy.maybeBlockExecuteCommand(args.command, toolCallId, ToolMessage, rootDir, allowedPathPrefixes);
49
+ return CommandPolicy.maybeBlockExecuteCommand(
50
+ args.command,
51
+ toolCallId,
52
+ ToolMessage,
53
+ rootDir,
54
+ allowedPathPrefixes,
55
+ policy?.commandPolicy,
56
+ );
35
57
  }
36
58
  return null;
37
59
  }
@@ -70,4 +92,16 @@ export class ToolCallGuard {
70
92
  ToolArgsNormalizer.resolveScriptSourcePath(rootDir, value).includes("/scripts/");
71
93
  });
72
94
  }
95
+
96
+ private static isInternalStatePath(args: ToolArgs, rootDir: string): boolean {
97
+ const normalizedRoot = rootDir.replace(/\\/g, "/");
98
+ return TOOL_PATH_ARG_KEYS.some((key) => {
99
+ const value = args[key];
100
+ if (typeof value !== "string" || !value.trim()) {
101
+ return false;
102
+ }
103
+ const resolved = ToolArgsNormalizer.resolveScriptSourcePath(rootDir, value);
104
+ return resolved === `${normalizedRoot}/.agent` || resolved.startsWith(`${normalizedRoot}/.agent/`);
105
+ });
106
+ }
73
107
  }
@@ -2,6 +2,7 @@ import type {
2
2
  HumanLoopService,
3
3
  HumanLoopToolPolicy,
4
4
  } from "../human-loop/humanLoop.js";
5
+ import type { AgentRuntimeMiddlewareSpec } from "../../config/resources.js";
5
6
 
6
7
  export const TOOL_PATH_ARG_KEYS = ["file_path", "path"] as const;
7
8
  export const MAX_LS_ENTRIES = 200;
@@ -80,6 +81,7 @@ export interface CreateAgentToolMiddlewareOptions {
80
81
  executeTimeoutMs?: number;
81
82
  blockTaskTool?: boolean;
82
83
  allowedToolNames?: string[];
84
+ policy?: AgentRuntimeMiddlewareSpec;
83
85
  logger?: (message: string) => void;
84
86
  persistTodos?: (todos: unknown[]) => Promise<void> | void;
85
87
  humanLoop?: HumanLoopService;
@@ -43,6 +43,7 @@ export interface CreateAgentRuntimeOptions
43
43
  emptyRunMaxRetries?: number;
44
44
  malformedToolCallMaxRetries?: number;
45
45
  idleTimeoutMaxRetries?: number;
46
+ resumeInterruptedRun?: boolean;
46
47
  heartbeatIntervalMs?: number;
47
48
  idleTimeoutMs?: number;
48
49
  artifactValidator?: (context: {
@@ -104,6 +105,7 @@ export class AgentRuntimeService implements AgentRuntime {
104
105
  defaultEmptyRunMaxRetries?: number;
105
106
  defaultMalformedToolCallMaxRetries?: number;
106
107
  defaultIdleTimeoutMaxRetries?: number;
108
+ defaultResumeInterruptedRun?: boolean;
107
109
  defaultHeartbeatIntervalMs?: number;
108
110
  defaultIdleTimeoutMs?: number;
109
111
  artifactValidator?: CreateAgentRuntimeOptions["artifactValidator"];
@@ -130,6 +132,7 @@ export class AgentRuntimeService implements AgentRuntime {
130
132
  defaultEmptyRunMaxRetries: params.defaultEmptyRunMaxRetries,
131
133
  defaultMalformedToolCallMaxRetries: params.defaultMalformedToolCallMaxRetries,
132
134
  defaultIdleTimeoutMaxRetries: params.defaultIdleTimeoutMaxRetries,
135
+ defaultResumeInterruptedRun: params.defaultResumeInterruptedRun,
133
136
  defaultHeartbeatIntervalMs: params.defaultHeartbeatIntervalMs,
134
137
  defaultIdleTimeoutMs: params.defaultIdleTimeoutMs,
135
138
  artifactValidator: params.artifactValidator,
@@ -27,7 +27,9 @@ export class RunArtifactService {
27
27
  todosFile: string,
28
28
  trackedArtifactFiles: string[],
29
29
  ): string[] {
30
- return [runStateFile, todosFile, ...trackedArtifactFiles]
30
+ void runStateFile;
31
+ void todosFile;
32
+ return trackedArtifactFiles
31
33
  .map((file) => relative(rootDir, file))
32
34
  .filter(Boolean);
33
35
  }
@@ -71,12 +71,30 @@ export class AgentRunStateStore {
71
71
 
72
72
  public buildResumePrompt(basePrompt: string, previousState: AgentRunState | null, resumeHint: string): string {
73
73
  if (previousState?.status !== "running") return basePrompt;
74
- return `${basePrompt}\n\n${resumeHint}`;
74
+ const checkpoint = {
75
+ threadId: previousState.threadId,
76
+ stepCount: previousState.stepCount,
77
+ lastSummary: previousState.lastSummary?.trim() || "n/a",
78
+ artifacts: this.summarizeArtifacts(previousState.artifacts),
79
+ rules: [
80
+ "Do not read .agent/*",
81
+ "Do not re-read existing outputs unless verification is required",
82
+ ],
83
+ resumeHint: resumeHint.trim() || undefined,
84
+ };
85
+ return `${basePrompt}\n\nRESUME_CHECKPOINT\n${JSON.stringify(checkpoint, null, 2)}`;
75
86
  }
76
87
 
77
88
  public getThreadId(previousState: AgentRunState | null, fallbackThreadId: string): string {
78
89
  return previousState?.status === "running" ? previousState.threadId : fallbackThreadId;
79
90
  }
91
+
92
+ private summarizeArtifacts(artifacts: Record<string, unknown>): Record<string, "ready" | "missing"> | undefined {
93
+ const entries = Object.entries(artifacts)
94
+ .filter(([key]) => /Present$/.test(key))
95
+ .map(([key, value]) => [key.replace(/Present$/, ""), value === true ? "ready" : "missing"] as const);
96
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
97
+ }
80
98
  }
81
99
 
82
100
  export function createAgentRunStateStore(options: CreateAgentRunStateStoreOptions) {