@capekai/core 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,3 +10,46 @@ Requires Bun 1.3 or newer.
10
10
  npm install @capekai/core
11
11
  ```
12
12
  Public subpaths include `composition`, `plugins`, `hosts`, `execution`, `providers`, `tools`, `ask-authority`, `sandbox`, `workspace`, `configuration`, `tool`, and `storage`.
13
+
14
+ ## Workspace policy
15
+
16
+ Čapek owns path resolution and containment. Embedding hosts can supply their own blocked paths, sensitive patterns, and home directory when composing an agent:
17
+
18
+ ```ts
19
+ import { createComposition } from '@capekai/core/composition';
20
+
21
+ const composition = await createComposition(processScope, {
22
+ ...values,
23
+ workspacePolicy: {
24
+ blockedPaths: ['/proc/', '/sys/'],
25
+ sensitivePatterns: ['.env', '.pem', '.key'],
26
+ homeDir: '/home/agent',
27
+ },
28
+ });
29
+ ```
30
+
31
+ Hosts building a custom plugin profile can configure the same policy directly:
32
+
33
+ ```ts
34
+ import { workspacePolicyPlugin } from '@capekai/core/plugins';
35
+
36
+ workspacePolicyPlugin('host.workspace-policy', {
37
+ blockedPaths: [],
38
+ sensitivePatterns: ['credentials'],
39
+ homeDir: '/srv/agent',
40
+ });
41
+ ```
42
+
43
+ For workspace helpers used outside an agent scope, configure the process-wide policy during host bootstrap:
44
+
45
+ ```ts
46
+ import { configureWorkspacePolicy } from '@capekai/core/workspace';
47
+
48
+ configureWorkspacePolicy({
49
+ blockedPaths: ['/proc/', '/sys/'],
50
+ sensitivePatterns: ['.env', '.pem', '.key'],
51
+ homeDir: '/home/agent',
52
+ });
53
+ ```
54
+
55
+ Call `configureWorkspacePolicy()` with no argument, or omit composition options, to retain the compatibility defaults.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capekai/core",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Bun-native composable agent runtime and framework for Capek.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  export {
12
+ configureWorkspacePolicy,
12
13
  expandPath,
13
14
  isInsideUnselectedAdditionalRoot,
14
15
  isPathInside,
@@ -16,6 +16,7 @@ import type { SandboxController } from '../sandbox/controller';
16
16
  import type { StorageBundle } from '../storage/contracts';
17
17
  import type { ToolRegistryResolver } from '../tools/registry';
18
18
  import type { WorkspaceToolDiscovery } from '../tools/tool-source';
19
+ import type { WorkspacePolicyOptions } from '../workspace/contracts';
19
20
  import { getSchedulerHost } from '../scheduler/host';
20
21
  import { getSessionSearchHost } from '../session-search/host';
21
22
  import { createContextSectionsPlugin } from './context-sections';
@@ -64,6 +65,9 @@ export interface FacadeScopeValues {
64
65
  host: RuntimeHost;
65
66
  contextSources: Partial<ContextSources>;
66
67
  workspaceToolDiscovery: WorkspaceToolDiscovery;
68
+ /** Host-owned path classification values. When omitted, the current
69
+ * compatibility defaults apply. */
70
+ workspacePolicy?: WorkspacePolicyOptions;
67
71
  /** Optional compatibility resolver. When omitted, the facade
68
72
  * composition derives the resolver from the composed scope's effective
69
73
  * contributed tool payloads. The explicit value is the rollback
@@ -109,7 +113,7 @@ export function createFacadeAgentPlugins(values: FacadeScopeValues): readonly Ca
109
113
  retryPolicyPlugin('facade.retry-policy'),
110
114
  compactionPolicyPlugin('facade.compaction-policy'),
111
115
  permissionPolicyPlugin('facade.permission-policy'),
112
- workspacePolicyPlugin('facade.workspace-policy'),
116
+ workspacePolicyPlugin('facade.workspace-policy', values.workspacePolicy),
113
117
  toolOutputPolicyPlugin('facade.tool-output-policy'),
114
118
  contextSourcesValuePlugin('facade.context-sources', values.contextSources),
115
119
  // Facade context parity: the facade keeps the legacy self-delegation and
@@ -1,11 +1,6 @@
1
1
  import type { CapekPlugin, PluginContext } from '../kernel/types';
2
- import { homedir } from 'os';
3
- import { SENSITIVE_FILE_PATTERNS } from '@capekai/types';
4
- import {
5
- BLOCKED_PATHS,
6
- createWorkspaceService,
7
- type WorkspacePolicyOptions,
8
- } from '../workspace/policy';
2
+ import type { WorkspacePolicyOptions } from '../workspace/contracts';
3
+ import { createWorkspaceService } from '../workspace/policy';
9
4
  import { capekWorkspacePolicyKey } from './service-keys';
10
5
 
11
6
  /**
@@ -17,17 +12,15 @@ import { capekWorkspacePolicyKey } from './service-keys';
17
12
  * current containment, root classification, expansion, and sensitive/blocked
18
13
  * denial behavior.
19
14
  */
20
- export function workspacePolicyPlugin(id: string): CapekPlugin<unknown> {
15
+ export function workspacePolicyPlugin(
16
+ id: string,
17
+ options?: WorkspacePolicyOptions,
18
+ ): CapekPlugin<unknown> {
21
19
  return {
22
20
  id,
23
21
  scope: 'agent',
24
22
  provides: [capekWorkspacePolicyKey],
25
23
  setup(context: PluginContext) {
26
- const options: WorkspacePolicyOptions = {
27
- blockedPaths: [...BLOCKED_PATHS],
28
- sensitivePatterns: [...SENSITIVE_FILE_PATTERNS],
29
- homeDir: homedir(),
30
- };
31
24
  context.provide(
32
25
  capekWorkspacePolicyKey,
33
26
  createWorkspaceService({ id, options }),
@@ -47,6 +47,14 @@ function defaultOptions(): WorkspacePolicyOptions {
47
47
  };
48
48
  }
49
49
 
50
+ function freezeOptions(options: WorkspacePolicyOptions): Readonly<WorkspacePolicyOptions> {
51
+ return Object.freeze({
52
+ blockedPaths: Object.freeze([...options.blockedPaths]),
53
+ sensitivePatterns: Object.freeze([...options.sensitivePatterns]),
54
+ homeDir: options.homeDir,
55
+ });
56
+ }
57
+
50
58
  // ── Mandatory containment runtime (C6 step 6) ───────────────────────────
51
59
  // The tool-runtime capability is constructed HERE, not by provider methods:
52
60
  // a custom provider supplies only frozen options (blocked paths, sensitive
@@ -130,7 +138,7 @@ export function createWorkspaceService(
130
138
  createOptions: WorkspaceServiceCreateOptions = {},
131
139
  ): WorkspaceService {
132
140
  const id = createOptions.id ?? 'workspace.default';
133
- const options = createOptions.options ?? defaultOptions();
141
+ const options = freezeOptions(createOptions.options ?? defaultOptions());
134
142
 
135
143
  const service: WorkspaceService = {
136
144
  id,
@@ -251,6 +259,15 @@ export function getWorkspaceService(): WorkspaceService {
251
259
  ?? (processDefaultService ??= createWorkspaceService({ id: 'workspace.process-default' }));
252
260
  }
253
261
 
262
+ /** Configures the process-wide policy used outside an agent scope. Omitting
263
+ * options restores the compatibility defaults. */
264
+ export function configureWorkspacePolicy(options?: WorkspacePolicyOptions): void {
265
+ processDefaultService = createWorkspaceService({
266
+ id: 'workspace.process-default',
267
+ options,
268
+ });
269
+ }
270
+
254
271
  /** Builds the tool-runtime capability over the active workspace policy. */
255
272
  export function createWorkspaceCapability(host: WorkspaceCapabilityHost): WorkspaceCapability {
256
273
  return createWorkspaceCapabilityWithOptions(host, getWorkspaceService().options);