@det-acp/core 0.2.1 → 0.3.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.
Files changed (57) hide show
  1. package/README.md +94 -32
  2. package/dist/engine/action-registry.d.ts.map +1 -1
  3. package/dist/engine/action-registry.js +20 -0
  4. package/dist/engine/action-registry.js.map +1 -1
  5. package/dist/index.d.ts +11 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +11 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/tools/archive-extract.d.ts +45 -0
  10. package/dist/tools/archive-extract.d.ts.map +1 -0
  11. package/dist/tools/archive-extract.js +246 -0
  12. package/dist/tools/archive-extract.js.map +1 -0
  13. package/dist/tools/directory-create.d.ts +33 -0
  14. package/dist/tools/directory-create.d.ts.map +1 -0
  15. package/dist/tools/directory-create.js +145 -0
  16. package/dist/tools/directory-create.js.map +1 -0
  17. package/dist/tools/directory-list.d.ts +32 -0
  18. package/dist/tools/directory-list.d.ts.map +1 -0
  19. package/dist/tools/directory-list.js +114 -0
  20. package/dist/tools/directory-list.js.map +1 -0
  21. package/dist/tools/env-read.d.ts +31 -0
  22. package/dist/tools/env-read.d.ts.map +1 -0
  23. package/dist/tools/env-read.js +108 -0
  24. package/dist/tools/env-read.js.map +1 -0
  25. package/dist/tools/file-copy.d.ts +30 -0
  26. package/dist/tools/file-copy.d.ts.map +1 -0
  27. package/dist/tools/file-copy.js +170 -0
  28. package/dist/tools/file-copy.js.map +1 -0
  29. package/dist/tools/file-delete.d.ts +27 -0
  30. package/dist/tools/file-delete.d.ts.map +1 -0
  31. package/dist/tools/file-delete.js +143 -0
  32. package/dist/tools/file-delete.js.map +1 -0
  33. package/dist/tools/file-move.d.ts +30 -0
  34. package/dist/tools/file-move.d.ts.map +1 -0
  35. package/dist/tools/file-move.js +167 -0
  36. package/dist/tools/file-move.js.map +1 -0
  37. package/dist/tools/git-commit.d.ts +33 -0
  38. package/dist/tools/git-commit.d.ts.map +1 -0
  39. package/dist/tools/git-commit.js +176 -0
  40. package/dist/tools/git-commit.js.map +1 -0
  41. package/dist/tools/git-status.d.ts +29 -0
  42. package/dist/tools/git-status.d.ts.map +1 -0
  43. package/dist/tools/git-status.js +159 -0
  44. package/dist/tools/git-status.js.map +1 -0
  45. package/dist/tools/network-dns.d.ts +50 -0
  46. package/dist/tools/network-dns.d.ts.map +1 -0
  47. package/dist/tools/network-dns.js +122 -0
  48. package/dist/tools/network-dns.js.map +1 -0
  49. package/dist/types.d.ts +1 -1
  50. package/dist/types.d.ts.map +1 -1
  51. package/examples/coding-agent.policy.yaml +44 -0
  52. package/examples/data-analyst.policy.yaml +160 -0
  53. package/examples/devops-deploy.policy.yaml +68 -0
  54. package/examples/infrastructure-manager.policy.yaml +209 -0
  55. package/examples/security-audit.policy.yaml +152 -0
  56. package/examples/video-upscaler.policy.yaml +45 -0
  57. package/package.json +1 -1
@@ -0,0 +1,170 @@
1
+ /**
2
+ * file:copy — Scoped file copy tool adapter.
3
+ *
4
+ * Copies files within allowed path scopes.
5
+ * Both source and destination must be within policy scope.
6
+ * Rollback support: removes the copied file (or restores overwritten content).
7
+ */
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ import crypto from 'node:crypto';
11
+ import { z } from 'zod';
12
+ import { ToolAdapter } from './base.js';
13
+ import { evaluateAction } from '../policy/evaluator.js';
14
+ export const FileCopyInputSchema = z.object({
15
+ source: z.string().min(1, 'Source path is required'),
16
+ destination: z.string().min(1, 'Destination path is required'),
17
+ /** Overwrite destination if it exists */
18
+ overwrite: z.boolean().default(false),
19
+ });
20
+ export class FileCopyAdapter extends ToolAdapter {
21
+ name = 'file:copy';
22
+ description = 'Copy a file within allowed path scopes';
23
+ inputSchema = FileCopyInputSchema;
24
+ validate(input, policy) {
25
+ const parsed = FileCopyInputSchema.safeParse(input);
26
+ if (!parsed.success) {
27
+ return {
28
+ verdict: 'deny',
29
+ tool: this.name,
30
+ reasons: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
31
+ };
32
+ }
33
+ // Source must be readable
34
+ const sourceResult = evaluateAction({ tool: 'file:read', input: { path: parsed.data.source } }, policy);
35
+ if (sourceResult.verdict === 'deny') {
36
+ return {
37
+ verdict: 'deny',
38
+ tool: this.name,
39
+ reasons: sourceResult.reasons.map((r) => `Source: ${r}`),
40
+ };
41
+ }
42
+ // Destination must be writable
43
+ const destResult = evaluateAction({ tool: 'file:write', input: { path: parsed.data.destination, content: '' } }, policy);
44
+ if (destResult.verdict === 'deny') {
45
+ return {
46
+ verdict: 'deny',
47
+ tool: this.name,
48
+ reasons: destResult.reasons.map((r) => `Destination: ${r}`),
49
+ };
50
+ }
51
+ // Evaluate the copy action itself for gate checks
52
+ return evaluateAction({ tool: this.name, input: parsed.data }, policy);
53
+ }
54
+ async dryRun(input, _ctx) {
55
+ const { source, destination, overwrite } = input;
56
+ const absSrc = path.resolve(source);
57
+ const absDest = path.resolve(destination);
58
+ const warnings = [];
59
+ if (!fs.existsSync(absSrc)) {
60
+ warnings.push(`Source file does not exist: ${absSrc}`);
61
+ }
62
+ if (fs.existsSync(absDest) && !overwrite) {
63
+ warnings.push(`Destination already exists and overwrite is false: ${absDest}`);
64
+ }
65
+ const destDir = path.dirname(absDest);
66
+ if (!fs.existsSync(destDir)) {
67
+ warnings.push(`Destination directory does not exist: ${destDir}`);
68
+ }
69
+ return {
70
+ tool: this.name,
71
+ wouldDo: `Copy ${absSrc} → ${absDest}`,
72
+ estimatedChanges: [absDest],
73
+ warnings,
74
+ };
75
+ }
76
+ async execute(input, ctx) {
77
+ const start = Date.now();
78
+ const { source, destination, overwrite } = input;
79
+ const absSrc = path.resolve(source);
80
+ const absDest = path.resolve(destination);
81
+ const artifacts = [];
82
+ try {
83
+ if (!fs.existsSync(absSrc)) {
84
+ return this.failure(`Source file does not exist: ${absSrc}`, Date.now() - start);
85
+ }
86
+ // Check destination
87
+ let destExisted = false;
88
+ let destPreviousContent = null;
89
+ if (fs.existsSync(absDest)) {
90
+ if (!overwrite) {
91
+ return this.failure(`Destination already exists: ${absDest}. Set overwrite: true to replace.`, Date.now() - start);
92
+ }
93
+ destExisted = true;
94
+ destPreviousContent = fs.readFileSync(absDest, 'base64');
95
+ }
96
+ // Read source and compute checksum
97
+ const srcContent = fs.readFileSync(absSrc);
98
+ const srcChecksum = crypto.createHash('sha256').update(srcContent).digest('hex');
99
+ artifacts.push({
100
+ type: 'checksum',
101
+ value: `sha256:${srcChecksum}`,
102
+ description: `Checksum of copied file`,
103
+ });
104
+ artifacts.push({
105
+ type: 'log',
106
+ value: `Copied: ${absSrc} → ${absDest} (${srcContent.length} bytes)`,
107
+ description: 'Copy record',
108
+ });
109
+ // Store rollback data
110
+ const rollbackKey = `file:copy:${absSrc}:${absDest}`;
111
+ ctx.rollbackData[rollbackKey] = {
112
+ destination: absDest,
113
+ destExisted,
114
+ destPreviousContent,
115
+ };
116
+ // Execute the copy
117
+ fs.copyFileSync(absSrc, absDest);
118
+ ctx.budget.filesChanged++;
119
+ ctx.budget.totalOutputBytes += srcContent.length;
120
+ return this.success({ source: absSrc, destination: absDest, size: srcContent.length }, Date.now() - start, artifacts);
121
+ }
122
+ catch (err) {
123
+ return this.failure(err.message, Date.now() - start);
124
+ }
125
+ }
126
+ async rollback(input, ctx) {
127
+ const { source, destination } = input;
128
+ const absSrc = path.resolve(source);
129
+ const absDest = path.resolve(destination);
130
+ const rollbackKey = `file:copy:${absSrc}:${absDest}`;
131
+ const rollbackData = ctx.rollbackData[rollbackKey];
132
+ if (!rollbackData) {
133
+ return {
134
+ tool: this.name,
135
+ success: false,
136
+ description: 'No rollback data available',
137
+ error: 'Rollback data not found — execute() may not have been called',
138
+ };
139
+ }
140
+ try {
141
+ if (rollbackData.destExisted && rollbackData.destPreviousContent !== null) {
142
+ // Restore overwritten destination
143
+ const content = Buffer.from(rollbackData.destPreviousContent, 'base64');
144
+ fs.writeFileSync(rollbackData.destination, content);
145
+ }
146
+ else {
147
+ // Remove the copied file
148
+ if (fs.existsSync(rollbackData.destination)) {
149
+ fs.unlinkSync(rollbackData.destination);
150
+ }
151
+ }
152
+ return {
153
+ tool: this.name,
154
+ success: true,
155
+ description: rollbackData.destExisted
156
+ ? `Restored original content at ${rollbackData.destination}`
157
+ : `Removed copied file ${rollbackData.destination}`,
158
+ };
159
+ }
160
+ catch (err) {
161
+ return {
162
+ tool: this.name,
163
+ success: false,
164
+ description: `Failed to rollback file copy`,
165
+ error: err.message,
166
+ };
167
+ }
168
+ }
169
+ }
170
+ //# sourceMappingURL=file-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-copy.js","sourceRoot":"","sources":["../../src/tools/file-copy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * file:delete — Scoped file deletion tool adapter.
3
+ *
4
+ * Deletes files within allowed path scopes, enforcing policy constraints.
5
+ * Creates a full backup of file contents for rollback support.
6
+ */
7
+ import { z } from 'zod';
8
+ import { ToolAdapter } from './base.js';
9
+ import type { DryRunResult, ExecutionContext, ExecutionResult, Policy, RollbackResult, ValidationResult } from '../types.js';
10
+ export declare const FileDeleteInputSchema: z.ZodObject<{
11
+ path: z.ZodString;
12
+ force: z.ZodDefault<z.ZodBoolean>;
13
+ }, z.core.$strip>;
14
+ export type FileDeleteInput = z.infer<typeof FileDeleteInputSchema>;
15
+ export declare class FileDeleteAdapter extends ToolAdapter {
16
+ readonly name = "file:delete";
17
+ readonly description = "Delete a file within allowed path scopes (with backup for rollback)";
18
+ readonly inputSchema: z.ZodObject<{
19
+ path: z.ZodString;
20
+ force: z.ZodDefault<z.ZodBoolean>;
21
+ }, z.core.$strip>;
22
+ validate(input: unknown, policy: Policy): ValidationResult;
23
+ dryRun(input: Record<string, unknown>, _ctx: ExecutionContext): Promise<DryRunResult>;
24
+ execute(input: Record<string, unknown>, ctx: ExecutionContext): Promise<ExecutionResult>;
25
+ rollback(input: Record<string, unknown>, ctx: ExecutionContext): Promise<RollbackResult>;
26
+ }
27
+ //# sourceMappingURL=file-delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-delete.d.ts","sourceRoot":"","sources":["../../src/tools/file-delete.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAEf,MAAM,EACN,cAAc,EACd,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,qBAAqB;;;iBAIhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,yEAAyE;IAC7F,QAAQ,CAAC,WAAW;;;sBAAyB;IAE7C,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAgBpD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAiCrF,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAgExF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC;CAsC/F"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * file:delete — Scoped file deletion tool adapter.
3
+ *
4
+ * Deletes files within allowed path scopes, enforcing policy constraints.
5
+ * Creates a full backup of file contents for rollback support.
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import crypto from 'node:crypto';
10
+ import { z } from 'zod';
11
+ import { ToolAdapter } from './base.js';
12
+ import { evaluateAction } from '../policy/evaluator.js';
13
+ export const FileDeleteInputSchema = z.object({
14
+ path: z.string().min(1, 'File path is required'),
15
+ /** If true, do not error when the file does not exist */
16
+ force: z.boolean().default(false),
17
+ });
18
+ export class FileDeleteAdapter extends ToolAdapter {
19
+ name = 'file:delete';
20
+ description = 'Delete a file within allowed path scopes (with backup for rollback)';
21
+ inputSchema = FileDeleteInputSchema;
22
+ validate(input, policy) {
23
+ const parsed = FileDeleteInputSchema.safeParse(input);
24
+ if (!parsed.success) {
25
+ return {
26
+ verdict: 'deny',
27
+ tool: this.name,
28
+ reasons: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
29
+ };
30
+ }
31
+ return evaluateAction({ tool: this.name, input: parsed.data }, policy);
32
+ }
33
+ async dryRun(input, _ctx) {
34
+ const { path: filePath, force } = input;
35
+ const absPath = path.resolve(filePath);
36
+ const exists = fs.existsSync(absPath);
37
+ const warnings = [];
38
+ if (!exists && !force) {
39
+ warnings.push(`File does not exist: ${absPath}`);
40
+ }
41
+ let size = 0;
42
+ if (exists) {
43
+ try {
44
+ const stat = fs.statSync(absPath);
45
+ size = stat.size;
46
+ if (stat.isDirectory()) {
47
+ warnings.push(`Path is a directory, not a file: ${absPath}`);
48
+ }
49
+ }
50
+ catch {
51
+ warnings.push(`Cannot stat file: ${absPath}`);
52
+ }
53
+ }
54
+ return {
55
+ tool: this.name,
56
+ wouldDo: exists
57
+ ? `Delete file: ${absPath} (${size} bytes)`
58
+ : `No-op: file does not exist: ${absPath}`,
59
+ estimatedChanges: exists ? [absPath] : [],
60
+ warnings,
61
+ };
62
+ }
63
+ async execute(input, ctx) {
64
+ const start = Date.now();
65
+ const { path: filePath, force } = input;
66
+ const absPath = path.resolve(filePath);
67
+ const artifacts = [];
68
+ try {
69
+ const exists = fs.existsSync(absPath);
70
+ if (!exists) {
71
+ if (force) {
72
+ return this.success({ path: absPath, deleted: false, reason: 'File did not exist' }, Date.now() - start);
73
+ }
74
+ return this.failure(`File does not exist: ${absPath}`, Date.now() - start);
75
+ }
76
+ // Verify it's a file, not a directory
77
+ const stat = fs.statSync(absPath);
78
+ if (stat.isDirectory()) {
79
+ return this.failure(`Path is a directory, not a file: ${absPath}`, Date.now() - start);
80
+ }
81
+ // Backup file content for rollback
82
+ const content = fs.readFileSync(absPath);
83
+ const checksum = crypto.createHash('sha256').update(content).digest('hex');
84
+ artifacts.push({
85
+ type: 'checksum',
86
+ value: `sha256:${checksum}`,
87
+ description: `Checksum of deleted file: ${absPath}`,
88
+ });
89
+ artifacts.push({
90
+ type: 'log',
91
+ value: `Deleted: ${absPath} (${stat.size} bytes)`,
92
+ description: 'Deletion record',
93
+ });
94
+ // Store rollback data (full content backup)
95
+ const rollbackKey = `file:delete:${absPath}`;
96
+ ctx.rollbackData[rollbackKey] = {
97
+ path: absPath,
98
+ content: content.toString('base64'),
99
+ mode: stat.mode,
100
+ };
101
+ // Delete the file
102
+ fs.unlinkSync(absPath);
103
+ ctx.budget.filesChanged++;
104
+ return this.success({ path: absPath, deleted: true, size: stat.size }, Date.now() - start, artifacts);
105
+ }
106
+ catch (err) {
107
+ return this.failure(err.message, Date.now() - start);
108
+ }
109
+ }
110
+ async rollback(input, ctx) {
111
+ const { path: filePath } = input;
112
+ const absPath = path.resolve(filePath);
113
+ const rollbackKey = `file:delete:${absPath}`;
114
+ const rollbackData = ctx.rollbackData[rollbackKey];
115
+ if (!rollbackData) {
116
+ return {
117
+ tool: this.name,
118
+ success: false,
119
+ description: 'No rollback data available',
120
+ error: 'Rollback data not found — execute() may not have been called',
121
+ };
122
+ }
123
+ try {
124
+ // Restore the file from the base64-encoded backup
125
+ const content = Buffer.from(rollbackData.content, 'base64');
126
+ fs.writeFileSync(rollbackData.path, content, { mode: rollbackData.mode });
127
+ return {
128
+ tool: this.name,
129
+ success: true,
130
+ description: `Restored deleted file: ${rollbackData.path}`,
131
+ };
132
+ }
133
+ catch (err) {
134
+ return {
135
+ tool: this.name,
136
+ success: false,
137
+ description: `Failed to restore deleted file: ${rollbackData.path}`,
138
+ error: err.message,
139
+ };
140
+ }
141
+ }
142
+ }
143
+ //# sourceMappingURL=file-delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-delete.js","sourceRoot":"","sources":["../../src/tools/file-delete.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * file:move — Scoped file move/rename tool adapter.
3
+ *
4
+ * Moves or renames files within allowed path scopes.
5
+ * Both source and destination must be within policy scope.
6
+ * Full rollback support: moves the file back to original location.
7
+ */
8
+ import { z } from 'zod';
9
+ import { ToolAdapter } from './base.js';
10
+ import type { DryRunResult, ExecutionContext, ExecutionResult, Policy, RollbackResult, ValidationResult } from '../types.js';
11
+ export declare const FileMoveInputSchema: z.ZodObject<{
12
+ source: z.ZodString;
13
+ destination: z.ZodString;
14
+ overwrite: z.ZodDefault<z.ZodBoolean>;
15
+ }, z.core.$strip>;
16
+ export type FileMoveInput = z.infer<typeof FileMoveInputSchema>;
17
+ export declare class FileMoveAdapter extends ToolAdapter {
18
+ readonly name = "file:move";
19
+ readonly description = "Move or rename a file within allowed path scopes";
20
+ readonly inputSchema: z.ZodObject<{
21
+ source: z.ZodString;
22
+ destination: z.ZodString;
23
+ overwrite: z.ZodDefault<z.ZodBoolean>;
24
+ }, z.core.$strip>;
25
+ validate(input: unknown, policy: Policy): ValidationResult;
26
+ dryRun(input: Record<string, unknown>, _ctx: ExecutionContext): Promise<DryRunResult>;
27
+ execute(input: Record<string, unknown>, ctx: ExecutionContext): Promise<ExecutionResult>;
28
+ rollback(input: Record<string, unknown>, ctx: ExecutionContext): Promise<RollbackResult>;
29
+ }
30
+ //# sourceMappingURL=file-move.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-move.d.ts","sourceRoot":"","sources":["../../src/tools/file-move.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAEf,MAAM,EACN,cAAc,EACd,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,mBAAmB;;;;iBAK9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,sDAAsD;IAC1E,QAAQ,CAAC,WAAW;;;;sBAAuB;IAE3C,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAyCpD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IA2BrF,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAmExF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC;CA+C/F"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * file:move — Scoped file move/rename tool adapter.
3
+ *
4
+ * Moves or renames files within allowed path scopes.
5
+ * Both source and destination must be within policy scope.
6
+ * Full rollback support: moves the file back to original location.
7
+ */
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ import crypto from 'node:crypto';
11
+ import { z } from 'zod';
12
+ import { ToolAdapter } from './base.js';
13
+ import { evaluateAction } from '../policy/evaluator.js';
14
+ export const FileMoveInputSchema = z.object({
15
+ source: z.string().min(1, 'Source path is required'),
16
+ destination: z.string().min(1, 'Destination path is required'),
17
+ /** Overwrite destination if it exists */
18
+ overwrite: z.boolean().default(false),
19
+ });
20
+ export class FileMoveAdapter extends ToolAdapter {
21
+ name = 'file:move';
22
+ description = 'Move or rename a file within allowed path scopes';
23
+ inputSchema = FileMoveInputSchema;
24
+ validate(input, policy) {
25
+ const parsed = FileMoveInputSchema.safeParse(input);
26
+ if (!parsed.success) {
27
+ return {
28
+ verdict: 'deny',
29
+ tool: this.name,
30
+ reasons: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
31
+ };
32
+ }
33
+ // Validate both source and destination paths against the policy
34
+ const sourceResult = evaluateAction({ tool: this.name, input: { ...parsed.data, path: parsed.data.source } }, policy);
35
+ if (sourceResult.verdict === 'deny') {
36
+ return {
37
+ ...sourceResult,
38
+ reasons: sourceResult.reasons.map((r) => `Source: ${r}`),
39
+ };
40
+ }
41
+ const destResult = evaluateAction({ tool: this.name, input: { ...parsed.data, path: parsed.data.destination } }, policy);
42
+ if (destResult.verdict === 'deny') {
43
+ return {
44
+ ...destResult,
45
+ reasons: destResult.reasons.map((r) => `Destination: ${r}`),
46
+ };
47
+ }
48
+ // Return the more restrictive result (gate > allow)
49
+ if (sourceResult.verdict === 'gate' || destResult.verdict === 'gate') {
50
+ return sourceResult.verdict === 'gate' ? sourceResult : destResult;
51
+ }
52
+ return sourceResult;
53
+ }
54
+ async dryRun(input, _ctx) {
55
+ const { source, destination, overwrite } = input;
56
+ const absSrc = path.resolve(source);
57
+ const absDest = path.resolve(destination);
58
+ const warnings = [];
59
+ if (!fs.existsSync(absSrc)) {
60
+ warnings.push(`Source file does not exist: ${absSrc}`);
61
+ }
62
+ if (fs.existsSync(absDest) && !overwrite) {
63
+ warnings.push(`Destination already exists and overwrite is false: ${absDest}`);
64
+ }
65
+ const destDir = path.dirname(absDest);
66
+ if (!fs.existsSync(destDir)) {
67
+ warnings.push(`Destination directory does not exist: ${destDir}`);
68
+ }
69
+ return {
70
+ tool: this.name,
71
+ wouldDo: `Move ${absSrc} → ${absDest}`,
72
+ estimatedChanges: [absSrc, absDest],
73
+ warnings,
74
+ };
75
+ }
76
+ async execute(input, ctx) {
77
+ const start = Date.now();
78
+ const { source, destination, overwrite } = input;
79
+ const absSrc = path.resolve(source);
80
+ const absDest = path.resolve(destination);
81
+ const artifacts = [];
82
+ try {
83
+ // Check source exists
84
+ if (!fs.existsSync(absSrc)) {
85
+ return this.failure(`Source file does not exist: ${absSrc}`, Date.now() - start);
86
+ }
87
+ // Check destination doesn't exist (unless overwrite)
88
+ let destExisted = false;
89
+ let destPreviousContent = null;
90
+ if (fs.existsSync(absDest)) {
91
+ if (!overwrite) {
92
+ return this.failure(`Destination already exists: ${absDest}. Set overwrite: true to replace.`, Date.now() - start);
93
+ }
94
+ destExisted = true;
95
+ destPreviousContent = fs.readFileSync(absDest, 'base64');
96
+ }
97
+ // Checksum source before move
98
+ const srcContent = fs.readFileSync(absSrc);
99
+ const srcChecksum = crypto.createHash('sha256').update(srcContent).digest('hex');
100
+ artifacts.push({
101
+ type: 'checksum',
102
+ value: `sha256:${srcChecksum}`,
103
+ description: `Checksum of moved file (source: ${absSrc})`,
104
+ });
105
+ artifacts.push({
106
+ type: 'log',
107
+ value: `Moved: ${absSrc} → ${absDest}`,
108
+ description: 'Move record',
109
+ });
110
+ // Store rollback data
111
+ const rollbackKey = `file:move:${absSrc}:${absDest}`;
112
+ ctx.rollbackData[rollbackKey] = {
113
+ source: absSrc,
114
+ destination: absDest,
115
+ destExisted,
116
+ destPreviousContent,
117
+ };
118
+ // Execute the move
119
+ fs.renameSync(absSrc, absDest);
120
+ ctx.budget.filesChanged++;
121
+ return this.success({ source: absSrc, destination: absDest, size: srcContent.length }, Date.now() - start, artifacts);
122
+ }
123
+ catch (err) {
124
+ return this.failure(err.message, Date.now() - start);
125
+ }
126
+ }
127
+ async rollback(input, ctx) {
128
+ const { source, destination } = input;
129
+ const absSrc = path.resolve(source);
130
+ const absDest = path.resolve(destination);
131
+ const rollbackKey = `file:move:${absSrc}:${absDest}`;
132
+ const rollbackData = ctx.rollbackData[rollbackKey];
133
+ if (!rollbackData) {
134
+ return {
135
+ tool: this.name,
136
+ success: false,
137
+ description: 'No rollback data available',
138
+ error: 'Rollback data not found — execute() may not have been called',
139
+ };
140
+ }
141
+ try {
142
+ // Move file back to original location
143
+ if (fs.existsSync(rollbackData.destination)) {
144
+ fs.renameSync(rollbackData.destination, rollbackData.source);
145
+ }
146
+ // Restore overwritten destination if applicable
147
+ if (rollbackData.destExisted && rollbackData.destPreviousContent !== null) {
148
+ const content = Buffer.from(rollbackData.destPreviousContent, 'base64');
149
+ fs.writeFileSync(rollbackData.destination, content);
150
+ }
151
+ return {
152
+ tool: this.name,
153
+ success: true,
154
+ description: `Moved ${rollbackData.destination} back to ${rollbackData.source}`,
155
+ };
156
+ }
157
+ catch (err) {
158
+ return {
159
+ tool: this.name,
160
+ success: false,
161
+ description: `Failed to rollback file move`,
162
+ error: err.message,
163
+ };
164
+ }
165
+ }
166
+ }
167
+ //# sourceMappingURL=file-move.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-move.js","sourceRoot":"","sources":["../../src/tools/file-move.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * git:commit — Scoped git commit tool adapter.
3
+ *
4
+ * Stages and commits changes in a repository.
5
+ * Rollback support via git revert.
6
+ */
7
+ import { z } from 'zod';
8
+ import { ToolAdapter } from './base.js';
9
+ import type { DryRunResult, ExecutionContext, ExecutionResult, Policy, RollbackResult, ValidationResult } from '../types.js';
10
+ export declare const GitCommitInputSchema: z.ZodObject<{
11
+ repo: z.ZodString;
12
+ message: z.ZodString;
13
+ paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
14
+ stageAll: z.ZodDefault<z.ZodBoolean>;
15
+ author: z.ZodOptional<z.ZodString>;
16
+ }, z.core.$strip>;
17
+ export type GitCommitInput = z.infer<typeof GitCommitInputSchema>;
18
+ export declare class GitCommitAdapter extends ToolAdapter {
19
+ readonly name = "git:commit";
20
+ readonly description = "Stage and commit changes in a git repository";
21
+ readonly inputSchema: z.ZodObject<{
22
+ repo: z.ZodString;
23
+ message: z.ZodString;
24
+ paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ stageAll: z.ZodDefault<z.ZodBoolean>;
26
+ author: z.ZodOptional<z.ZodString>;
27
+ }, z.core.$strip>;
28
+ validate(input: unknown, policy: Policy): ValidationResult;
29
+ dryRun(input: Record<string, unknown>, _ctx: ExecutionContext): Promise<DryRunResult>;
30
+ execute(input: Record<string, unknown>, ctx: ExecutionContext): Promise<ExecutionResult>;
31
+ rollback(input: Record<string, unknown>, ctx: ExecutionContext): Promise<RollbackResult>;
32
+ }
33
+ //# sourceMappingURL=git-commit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-commit.d.ts","sourceRoot":"","sources":["../../src/tools/git-commit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAEf,MAAM,EACN,cAAc,EACd,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,oBAAoB;;;;;;iBAS/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,kDAAkD;IACtE,QAAQ,CAAC,WAAW;;;;;;sBAAwB;IAE5C,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAgBpD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IA2BrF,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA8ExF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC;CA4D/F"}