@vinhnt-sdk/tools 1.0.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 (146) hide show
  1. package/LICENSE +21 -0
  2. package/dist/arity.d.ts +22 -0
  3. package/dist/arity.d.ts.map +1 -0
  4. package/dist/arity.js +96 -0
  5. package/dist/arity.js.map +1 -0
  6. package/dist/context.d.ts +43 -0
  7. package/dist/context.d.ts.map +1 -0
  8. package/dist/context.js +2 -0
  9. package/dist/context.js.map +1 -0
  10. package/dist/define-tool.d.ts +45 -0
  11. package/dist/define-tool.d.ts.map +1 -0
  12. package/dist/define-tool.js +120 -0
  13. package/dist/define-tool.js.map +1 -0
  14. package/dist/definitions.d.ts +24 -0
  15. package/dist/definitions.d.ts.map +1 -0
  16. package/dist/definitions.js +2 -0
  17. package/dist/definitions.js.map +1 -0
  18. package/dist/description-lint.d.ts +25 -0
  19. package/dist/description-lint.d.ts.map +1 -0
  20. package/dist/description-lint.js +90 -0
  21. package/dist/description-lint.js.map +1 -0
  22. package/dist/diff.d.ts +7 -0
  23. package/dist/diff.d.ts.map +1 -0
  24. package/dist/diff.js +26 -0
  25. package/dist/diff.js.map +1 -0
  26. package/dist/domain.d.ts +39 -0
  27. package/dist/domain.d.ts.map +1 -0
  28. package/dist/domain.js +20 -0
  29. package/dist/domain.js.map +1 -0
  30. package/dist/file-history.d.ts +43 -0
  31. package/dist/file-history.d.ts.map +1 -0
  32. package/dist/file-history.js +55 -0
  33. package/dist/file-history.js.map +1 -0
  34. package/dist/file-tools.d.ts +56 -0
  35. package/dist/file-tools.d.ts.map +1 -0
  36. package/dist/file-tools.js +542 -0
  37. package/dist/file-tools.js.map +1 -0
  38. package/dist/git-tools.d.ts +8 -0
  39. package/dist/git-tools.d.ts.map +1 -0
  40. package/dist/git-tools.js +114 -0
  41. package/dist/git-tools.js.map +1 -0
  42. package/dist/history-hook.d.ts +4 -0
  43. package/dist/history-hook.d.ts.map +1 -0
  44. package/dist/history-hook.js +62 -0
  45. package/dist/history-hook.js.map +1 -0
  46. package/dist/image-tools.d.ts +11 -0
  47. package/dist/image-tools.d.ts.map +1 -0
  48. package/dist/image-tools.js +55 -0
  49. package/dist/image-tools.js.map +1 -0
  50. package/dist/index.d.ts +57 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +36 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/json-schema.d.ts +22 -0
  55. package/dist/json-schema.d.ts.map +1 -0
  56. package/dist/json-schema.js +2 -0
  57. package/dist/json-schema.js.map +1 -0
  58. package/dist/lazy-registry.d.ts +23 -0
  59. package/dist/lazy-registry.d.ts.map +1 -0
  60. package/dist/lazy-registry.js +64 -0
  61. package/dist/lazy-registry.js.map +1 -0
  62. package/dist/policy.d.ts +5 -0
  63. package/dist/policy.d.ts.map +1 -0
  64. package/dist/policy.js +2 -0
  65. package/dist/policy.js.map +1 -0
  66. package/dist/provider-helpers.d.ts +26 -0
  67. package/dist/provider-helpers.d.ts.map +1 -0
  68. package/dist/provider-helpers.js +46 -0
  69. package/dist/provider-helpers.js.map +1 -0
  70. package/dist/provider.d.ts +80 -0
  71. package/dist/provider.d.ts.map +1 -0
  72. package/dist/provider.js +96 -0
  73. package/dist/provider.js.map +1 -0
  74. package/dist/providers/agent-provider.d.ts +32 -0
  75. package/dist/providers/agent-provider.d.ts.map +1 -0
  76. package/dist/providers/agent-provider.js +35 -0
  77. package/dist/providers/agent-provider.js.map +1 -0
  78. package/dist/providers/builtin-provider.d.ts +36 -0
  79. package/dist/providers/builtin-provider.d.ts.map +1 -0
  80. package/dist/providers/builtin-provider.js +86 -0
  81. package/dist/providers/builtin-provider.js.map +1 -0
  82. package/dist/providers/file-loader.d.ts +47 -0
  83. package/dist/providers/file-loader.d.ts.map +1 -0
  84. package/dist/providers/file-loader.js +120 -0
  85. package/dist/providers/file-loader.js.map +1 -0
  86. package/dist/providers/index.d.ts +6 -0
  87. package/dist/providers/index.d.ts.map +1 -0
  88. package/dist/providers/index.js +5 -0
  89. package/dist/providers/index.js.map +1 -0
  90. package/dist/providers/skill-provider.d.ts +23 -0
  91. package/dist/providers/skill-provider.d.ts.map +1 -0
  92. package/dist/providers/skill-provider.js +28 -0
  93. package/dist/providers/skill-provider.js.map +1 -0
  94. package/dist/question-tool.d.ts +15 -0
  95. package/dist/question-tool.d.ts.map +1 -0
  96. package/dist/question-tool.js +51 -0
  97. package/dist/question-tool.js.map +1 -0
  98. package/dist/read-tracker.d.ts +8 -0
  99. package/dist/read-tracker.d.ts.map +1 -0
  100. package/dist/read-tracker.js +33 -0
  101. package/dist/read-tracker.js.map +1 -0
  102. package/dist/registry.d.ts +58 -0
  103. package/dist/registry.d.ts.map +1 -0
  104. package/dist/registry.js +128 -0
  105. package/dist/registry.js.map +1 -0
  106. package/dist/sandbox.d.ts +85 -0
  107. package/dist/sandbox.d.ts.map +1 -0
  108. package/dist/sandbox.js +409 -0
  109. package/dist/sandbox.js.map +1 -0
  110. package/dist/search-tools.d.ts +11 -0
  111. package/dist/search-tools.d.ts.map +1 -0
  112. package/dist/search-tools.js +124 -0
  113. package/dist/search-tools.js.map +1 -0
  114. package/dist/shell-parser.d.ts +9 -0
  115. package/dist/shell-parser.d.ts.map +1 -0
  116. package/dist/shell-parser.js +68 -0
  117. package/dist/shell-parser.js.map +1 -0
  118. package/dist/shell-tool.d.ts +22 -0
  119. package/dist/shell-tool.d.ts.map +1 -0
  120. package/dist/shell-tool.js +100 -0
  121. package/dist/shell-tool.js.map +1 -0
  122. package/dist/todo-tool.d.ts +2 -0
  123. package/dist/todo-tool.d.ts.map +1 -0
  124. package/dist/todo-tool.js +121 -0
  125. package/dist/todo-tool.js.map +1 -0
  126. package/dist/tool-search.d.ts +14 -0
  127. package/dist/tool-search.d.ts.map +1 -0
  128. package/dist/tool-search.js +46 -0
  129. package/dist/tool-search.js.map +1 -0
  130. package/dist/types.d.ts +30 -0
  131. package/dist/types.d.ts.map +1 -0
  132. package/dist/types.js +2 -0
  133. package/dist/types.js.map +1 -0
  134. package/dist/validate.d.ts +9 -0
  135. package/dist/validate.d.ts.map +1 -0
  136. package/dist/validate.js +26 -0
  137. package/dist/validate.js.map +1 -0
  138. package/dist/web-search-tool.d.ts +84 -0
  139. package/dist/web-search-tool.d.ts.map +1 -0
  140. package/dist/web-search-tool.js +134 -0
  141. package/dist/web-search-tool.js.map +1 -0
  142. package/dist/web-tools.d.ts +10 -0
  143. package/dist/web-tools.d.ts.map +1 -0
  144. package/dist/web-tools.js +62 -0
  145. package/dist/web-tools.js.map +1 -0
  146. package/package.json +58 -0
@@ -0,0 +1,15 @@
1
+ export interface QuestionInput {
2
+ header: string;
3
+ question: string;
4
+ options?: {
5
+ label: string;
6
+ description?: string;
7
+ }[] | undefined;
8
+ multiple?: boolean;
9
+ }
10
+ export type QuestionHandler = (question: QuestionInput) => Promise<string>;
11
+ export declare function createQuestionTool(handler?: QuestionHandler): import("./definitions.js").ToolDefinition<QuestionInput, {
12
+ answer: string;
13
+ error?: string;
14
+ }>;
15
+ //# sourceMappingURL=question-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-tool.d.ts","sourceRoot":"","sources":["../src/question-tool.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,SAAS,CAAC;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAY3E,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,eAAe;YACf,MAAM;YAAU,MAAM;GAqClE"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ import { defineTool } from "./define-tool.js";
3
+ const QuestionSchema = z.object({
4
+ header: z.string().min(1).max(30),
5
+ question: z.string().min(1),
6
+ options: z.array(z.object({
7
+ label: z.string().min(1),
8
+ description: z.string().optional(),
9
+ })).min(1).max(6).optional(),
10
+ multiple: z.boolean().optional(),
11
+ });
12
+ export function createQuestionTool(handler) {
13
+ return defineTool({
14
+ name: "question",
15
+ description: "Ask the user a question and get their response. Use this when you need clarification, preferences, or decisions from the user. Provide clear options when possible.",
16
+ risk: "external",
17
+ input: QuestionSchema,
18
+ jsonSchema: {
19
+ type: "object",
20
+ properties: {
21
+ header: { type: "string", description: "Short header or title for the question (max 100 chars)" },
22
+ question: { type: "string", description: "The question to ask the user" },
23
+ options: {
24
+ type: "array",
25
+ items: {
26
+ type: "object",
27
+ properties: {
28
+ label: { type: "string", description: "Option label shown to user" },
29
+ description: { type: "string", description: "Optional description" },
30
+ },
31
+ required: ["label"],
32
+ },
33
+ description: "Predefined answer options the user can pick from",
34
+ },
35
+ multiple: {
36
+ type: "boolean",
37
+ description: "Allow selecting multiple options (default: false)",
38
+ },
39
+ },
40
+ required: ["header", "question"],
41
+ },
42
+ async execute(v) {
43
+ if (!handler) {
44
+ return { answer: "", error: "No question handler configured" };
45
+ }
46
+ const answer = await handler(v);
47
+ return { answer };
48
+ },
49
+ }).toDefinition();
50
+ }
51
+ //# sourceMappingURL=question-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-tool.js","sourceRoot":"","sources":["../src/question-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAW9C,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACjC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACxB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACnC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAAC,OAAyB;IAC1D,OAAO,UAAU,CAAoD;QACnE,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,qKAAqK;QAClL,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,cAAc;QACrB,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wDAAwD,EAAE;gBACjG,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;gBACzE,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4BAA4B,EAAE;4BACpE,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;yBACrE;wBACD,QAAQ,EAAE,CAAC,OAAO,CAAC;qBACpB;oBACD,WAAW,EAAE,kDAAkD;iBAChE;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,mDAAmD;iBACjE;aACF;YACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjC;QACD,KAAK,CAAC,OAAO,CAAC,CAAC;YACb,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC;YACjE,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,CAAC;KACF,CAAC,CAAC,YAAY,EAAE,CAAC;AACpB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare class FileReadTracker {
2
+ private records;
3
+ trackRead(filePath: string, mtimeMs: number): void;
4
+ assertWasRead(filePath: string): Promise<void>;
5
+ clear(filePath: string): void;
6
+ reset(): void;
7
+ }
8
+ //# sourceMappingURL=read-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-tracker.d.ts","sourceRoot":"","sources":["../src/read-tracker.ts"],"names":[],"mappings":"AAQA,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAiC;IAEhD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5C,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpD,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI7B,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,33 @@
1
+ import { stat } from "node:fs/promises";
2
+ import { ToolPermissionDenied } from "@vinhnt-sdk/schema";
3
+ export class FileReadTracker {
4
+ records = new Map();
5
+ trackRead(filePath, mtimeMs) {
6
+ this.records.set(filePath, { readAt: Date.now(), mtimeMs });
7
+ }
8
+ async assertWasRead(filePath) {
9
+ const record = this.records.get(filePath);
10
+ if (!record) {
11
+ throw new ToolPermissionDenied("write_file", `File "${filePath}" has not been read before writing. Use read_file first.`);
12
+ }
13
+ try {
14
+ const st = await stat(filePath);
15
+ if (st.mtimeMs !== record.mtimeMs) {
16
+ this.records.delete(filePath);
17
+ throw new ToolPermissionDenied("write_file", `File "${filePath}" has been modified externally since it was last read. Read it again before writing.`);
18
+ }
19
+ }
20
+ catch (err) {
21
+ if (err instanceof ToolPermissionDenied)
22
+ throw err;
23
+ this.records.delete(filePath);
24
+ }
25
+ }
26
+ clear(filePath) {
27
+ this.records.delete(filePath);
28
+ }
29
+ reset() {
30
+ this.records.clear();
31
+ }
32
+ }
33
+ //# sourceMappingURL=read-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-tracker.js","sourceRoot":"","sources":["../src/read-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAO1D,MAAM,OAAO,eAAe;IAClB,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAEhD,SAAS,CAAC,QAAgB,EAAE,OAAe;QACzC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,oBAAoB,CAC5B,YAAY,EACZ,SAAS,QAAQ,0DAA0D,CAC5E,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,EAAE,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC9B,MAAM,IAAI,oBAAoB,CAC5B,YAAY,EACZ,SAAS,QAAQ,sFAAsF,CACxG,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,oBAAoB;gBAAE,MAAM,GAAG,CAAC;YACnD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAgB;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,58 @@
1
+ import type { ToolDefinition, ToolContext, ToolRisk } from "./definitions.js";
2
+ import type { DomainManifest, DomainSummary } from "./domain.js";
3
+ export type ToolFilter = {
4
+ risk?: ToolRisk;
5
+ ids?: string[];
6
+ pattern?: string;
7
+ };
8
+ /** Minimal permission rule relevant for tool filtering at the tool boundary. */
9
+ export interface ToolPermissionRule {
10
+ /** Tool id or wildcard pattern (e.g. "coding.*", "*"). */
11
+ action: string;
12
+ effect: "allow" | "deny" | "ask";
13
+ }
14
+ export interface ToolMaterialization {
15
+ /** Provider-facing definitions the model is ALLOWED to see/invoke. */
16
+ definitions: readonly ToolDefinition[];
17
+ /** Tool definitions that were denied by permission rules. */
18
+ denied: readonly ToolDefinition[];
19
+ /** Resolve one tool call: validate args and execute. */
20
+ settle(input: {
21
+ name: string;
22
+ args: unknown;
23
+ ctx?: ToolContext;
24
+ }): Promise<unknown>;
25
+ /** Lookup a tool definition by ID from the allowed set. */
26
+ getTool(id: string): ToolDefinition | undefined;
27
+ }
28
+ export declare class ToolRegistry {
29
+ protected readonly tools: Map<string, ToolDefinition<unknown, unknown>>;
30
+ protected readonly domains: Map<string, DomainManifest>;
31
+ register(tool: ToolDefinition): void;
32
+ /** Register a named domain and its tool membership (metadata only — does not register the tools). */
33
+ registerDomain(manifest: DomainManifest): void;
34
+ getDomains(): readonly DomainManifest[];
35
+ /** Resolve the domain id a tool belongs to, or undefined if it is a core tool. */
36
+ domainFor(id: string): string | undefined;
37
+ /** Get all registered domain manifests. */
38
+ listDomains(): readonly DomainManifest[];
39
+ /** Get domain summaries for UI/API consumption. */
40
+ domainSummaries(): DomainSummary[];
41
+ /** Get tools belonging to a specific domain. */
42
+ toolsForDomain(domainId: string): readonly ToolDefinition[];
43
+ unregister(id: string): boolean;
44
+ get(id: string): ToolDefinition | undefined;
45
+ list(filter?: ToolFilter): readonly ToolDefinition[];
46
+ count(): number;
47
+ /** Get a tool by ID, throwing a typed error if not found */
48
+ getOrThrow(id: string): ToolDefinition;
49
+ /**
50
+ * Materialize the tool set for a given permission ruleset: drop tools the
51
+ * model must not see (wholly-denied), and return a `settle` that validates
52
+ * and executes a single tool call. Defaults to exposing every registered tool.
53
+ */
54
+ materialize(permissions?: readonly ToolPermissionRule[]): ToolMaterialization;
55
+ /** Remove tools whose rule is wholly denied (deny "*" / deny this tool). */
56
+ private filterByRules;
57
+ }
58
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG9E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjE,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,WAAW,EAAE,SAAS,cAAc,EAAE,CAAC;IACvC,6DAA6D;IAC7D,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAClC,wDAAwD;IACxD,MAAM,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,2DAA2D;IAC3D,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;CACjD;AAED,qBAAa,YAAY;IACvB,SAAS,CAAC,QAAQ,CAAC,KAAK,gDAAqC;IAC7D,SAAS,CAAC,QAAQ,CAAC,OAAO,8BAAqC;IAE/D,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAIpC,qGAAqG;IACrG,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAI9C,UAAU,IAAI,SAAS,cAAc,EAAE;IAIvC,kFAAkF;IAClF,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOzC,2CAA2C;IAC3C,WAAW,IAAI,SAAS,cAAc,EAAE;IAIxC,mDAAmD;IACnD,eAAe,IAAI,aAAa,EAAE;IAIlC,gDAAgD;IAChD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE;IAK3D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI3C,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,cAAc,EAAE;IAWpD,KAAK,IAAI,MAAM;IAIf,4DAA4D;IAC5D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc;IAMtC;;;;OAIG;IACH,WAAW,CAAC,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,GAAG,mBAAmB;IAmC7E,4EAA4E;IAC5E,OAAO,CAAC,aAAa;CAWtB"}
@@ -0,0 +1,128 @@
1
+ import { wildcardMatch } from "@vinhnt-sdk/schema";
2
+ import { ToolNotFoundError } from "@vinhnt-sdk/schema";
3
+ import { summarizeDomains } from "./domain.js";
4
+ import { validateInput } from "./validate.js";
5
+ export class ToolRegistry {
6
+ tools = new Map();
7
+ domains = new Map();
8
+ register(tool) {
9
+ this.tools.set(tool.id, tool);
10
+ }
11
+ /** Register a named domain and its tool membership (metadata only — does not register the tools). */
12
+ registerDomain(manifest) {
13
+ this.domains.set(manifest.id, manifest);
14
+ }
15
+ getDomains() {
16
+ return [...this.domains.values()];
17
+ }
18
+ /** Resolve the domain id a tool belongs to, or undefined if it is a core tool. */
19
+ domainFor(id) {
20
+ for (const [domainId, manifest] of this.domains) {
21
+ if (manifest.tools.some((t) => t.id === id))
22
+ return domainId;
23
+ }
24
+ return undefined;
25
+ }
26
+ /** Get all registered domain manifests. */
27
+ listDomains() {
28
+ return [...this.domains.values()];
29
+ }
30
+ /** Get domain summaries for UI/API consumption. */
31
+ domainSummaries() {
32
+ return summarizeDomains([...this.domains.values()]);
33
+ }
34
+ /** Get tools belonging to a specific domain. */
35
+ toolsForDomain(domainId) {
36
+ const manifest = this.domains.get(domainId);
37
+ return manifest?.tools ?? [];
38
+ }
39
+ unregister(id) {
40
+ return this.tools.delete(id);
41
+ }
42
+ get(id) {
43
+ return this.tools.get(id);
44
+ }
45
+ list(filter) {
46
+ const all = [...this.tools.values()];
47
+ if (!filter)
48
+ return all;
49
+ return all.filter((t) => {
50
+ if (filter.risk && t.risk !== filter.risk)
51
+ return false;
52
+ if (filter.ids && !filter.ids.includes(t.id))
53
+ return false;
54
+ if (filter.pattern && !wildcardMatch(filter.pattern, t.id))
55
+ return false;
56
+ return true;
57
+ });
58
+ }
59
+ count() {
60
+ return this.tools.size;
61
+ }
62
+ /** Get a tool by ID, throwing a typed error if not found */
63
+ getOrThrow(id) {
64
+ const tool = this.tools.get(id);
65
+ if (!tool)
66
+ throw new ToolNotFoundError(id);
67
+ return tool;
68
+ }
69
+ /**
70
+ * Materialize the tool set for a given permission ruleset: drop tools the
71
+ * model must not see (wholly-denied), and return a `settle` that validates
72
+ * and executes a single tool call. Defaults to exposing every registered tool.
73
+ */
74
+ materialize(permissions) {
75
+ const allTools = [...this.tools.values()];
76
+ const allowed = this.filterByRules(allTools, permissions);
77
+ const allowedIds = new Set(allowed.map((t) => t.id));
78
+ const denied = allTools.filter((t) => !allowedIds.has(t.id));
79
+ const allowedMap = new Map(allowed.map((t) => [t.id, t]));
80
+ return {
81
+ definitions: allowed,
82
+ denied,
83
+ getTool: (id) => allowedMap.get(id),
84
+ settle: async ({ name, args, ctx }) => {
85
+ const tool = this.tools.get(name);
86
+ if (!tool)
87
+ throw new ToolNotFoundError(name);
88
+ // Validate input via Zod schema if available (non-breaking: falls through to raw execute if no schema)
89
+ let validatedInput = args;
90
+ if (tool.inputZodSchema) {
91
+ validatedInput = validateInput(name, tool.inputZodSchema, args);
92
+ }
93
+ const defaultCtx = {
94
+ sessionId: "",
95
+ runId: "",
96
+ agentId: "",
97
+ agentName: "",
98
+ signal: new AbortController().signal,
99
+ env: {},
100
+ ask: async () => "once",
101
+ metadata: () => { },
102
+ setCompensation: () => { },
103
+ };
104
+ return tool.execute(validatedInput, ctx ?? defaultCtx);
105
+ },
106
+ };
107
+ }
108
+ /** Remove tools whose rule is wholly denied (deny "*" / deny this tool). */
109
+ filterByRules(tools, permissions) {
110
+ if (!permissions || permissions.length === 0)
111
+ return tools;
112
+ const deniedActions = new Set();
113
+ for (const rule of permissions) {
114
+ if (rule.effect === "deny")
115
+ deniedActions.add(rule.action);
116
+ }
117
+ return tools.filter((t) => isDenied(t.id, deniedActions) === false);
118
+ }
119
+ }
120
+ /** A tool is denied if it matches a deny rule (exact or wildcard). */
121
+ function isDenied(id, deniedActions) {
122
+ for (const pattern of deniedActions) {
123
+ if (wildcardMatch(pattern, id))
124
+ return true;
125
+ }
126
+ return false;
127
+ }
128
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Tool sandboxing for isolated execution.
3
+ *
4
+ * @module tool/sandbox
5
+ * @packageDocumentation
6
+ */
7
+ import type { ToolDefinition, ToolContext } from "./definitions.js";
8
+ /** Sandbox execution scope — string type, NOT closed union */
9
+ export type SandboxScope = string;
10
+ /**
11
+ * Default sandbox scopes — exported for convenience.
12
+ * User có thể register custom scope qua ProcessSandbox adapter.
13
+ */
14
+ export declare const KNOWN_SANDBOX_SCOPES: readonly ["host", "process", "container"];
15
+ /** Sandbox configuration */
16
+ export interface SandboxConfig {
17
+ defaultTimeoutMs: number;
18
+ /** Execution scope (default: "host" — no isolation) */
19
+ scope?: SandboxScope;
20
+ /** Allowed filesystem paths (for "process" scope) */
21
+ allowedPaths?: string[];
22
+ /** Blocked filesystem paths */
23
+ blockedPaths?: string[];
24
+ /** Allow network access (default: true) */
25
+ allowNetwork?: boolean;
26
+ /** Allowed environment variables */
27
+ allowedEnvVars?: string[];
28
+ /** Allowed commands (for "process" scope) */
29
+ allowedCommands?: Set<string>;
30
+ /** Enable Node.js Permission Model (Node 22+) */
31
+ enablePermissionModel?: boolean;
32
+ }
33
+ /** Result of a sandboxed execution */
34
+ export interface SandboxResult<T = unknown> {
35
+ result: T;
36
+ exitCode: number;
37
+ durationMs: number;
38
+ timedOut: boolean;
39
+ /** Resources consumed during execution */
40
+ resources?: {
41
+ cpuTimeMs?: number;
42
+ memoryBytes?: number;
43
+ };
44
+ }
45
+ /**
46
+ * Interface for sandbox execution adapters.
47
+ *
48
+ * Implementations can provide different levels of isolation:
49
+ * - `host`: No isolation (current behavior)
50
+ * - `process`: Node.js Permission Model + empty env + command allowlist
51
+ * - `container`: Docker/Firecracker microVM
52
+ */
53
+ export interface ProcessSandbox {
54
+ /** The scope this sandbox provides */
55
+ readonly scope: SandboxScope;
56
+ /** Execute a command in the sandbox */
57
+ execute(options: {
58
+ command: string;
59
+ cwd: string;
60
+ timeoutMs: number;
61
+ env?: Record<string, string>;
62
+ signal?: AbortSignal;
63
+ }): Promise<SandboxResult<{
64
+ stdout: string;
65
+ stderr: string;
66
+ exitCode: number;
67
+ }>>;
68
+ /** Clean up resources */
69
+ destroy(): Promise<void>;
70
+ }
71
+ /**
72
+ * Create a process sandbox based on the configured scope.
73
+ *
74
+ * @param config - Sandbox configuration
75
+ * @returns ProcessSandbox instance
76
+ */
77
+ export declare function createSandbox(config: SandboxConfig): ProcessSandbox;
78
+ /** Create a minimal ToolContext from an AbortSignal (for backward compat) */
79
+ export declare function signalToToolContext(signal?: AbortSignal): ToolContext;
80
+ export declare class ToolSandbox {
81
+ private readonly config;
82
+ constructor(config?: SandboxConfig);
83
+ execute(tool: ToolDefinition, input: unknown, ctx: ToolContext): Promise<unknown>;
84
+ }
85
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA6HpE,8DAA8D;AAC9D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,2CAA4C,CAAC;AAE9E,4BAA4B;AAC5B,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oCAAoC;IACpC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6CAA6C;IAC7C,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,iDAAiD;IACjD,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,MAAM,EAAE,CAAC,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE;QACV,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAE7B,uCAAuC;IACvC,OAAO,CAAC,OAAO,EAAE;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,OAAO,CAAC,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAEjF,yBAAyB;IACzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AA0PD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAUnE;AAMD,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,CAgBrE;AAED,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,GAAE,aAA4C;IAE3E,OAAO,CACX,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,OAAO,CAAC;CAcpB"}