@botbotgo/agent-harness 0.0.162 → 0.0.164

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
@@ -26,6 +26,11 @@
26
26
  (static page in <code>docs/</code>, publish with GitHub Pages; EN / 中文 toggle)
27
27
  </p>
28
28
 
29
+ <p align="center">
30
+ <a href="https://botbotgo.github.io/agent-harness/development/">Developer docs</a>
31
+ (multi-page static docs in <code>docs/development/</code>)
32
+ </p>
33
+
29
34
  <p align="center">
30
35
  <em
31
36
  >We specialize in AI solutions. If you have a product idea you want to ship,
@@ -142,6 +147,13 @@ The default rule is:
142
147
 
143
148
  Boundary documents live in:
144
149
 
150
+ - `docs/development/index.html`
151
+ - `docs/development/getting-started.html`
152
+ - `docs/development/application-model.html`
153
+ - `docs/development/workspace-and-yaml.html`
154
+ - `docs/development/extensions.html`
155
+ - `docs/development/runtime-operations.html`
156
+ - `docs/development/testing-and-release.html`
145
157
  - `docs/upstream-feature-matrix.md`
146
158
  - `docs/product-boundary.md`
147
159
  - `docs/runtime-blueprint-assessment.md`
@@ -578,6 +590,7 @@ Example workspaces:
578
590
 
579
591
  Workspace-local tool modules in `resources/tools/` should be exported with `tool({...})`.
580
592
  Any other local module shape is not supported, and unsupported shapes are rejected at load time.
593
+ When a local function tool declares its schema in the module, runtime governance treats that module-defined schema as the source of truth; duplicating it into YAML `inputSchema.ref` is optional rather than required for schema-bound metadata.
581
594
  When local tools use Zod-authored schemas, keep the workspace or isolated `resources` package on `zod@^4` so raw-shape validators and runtime parsing stay on one supported major version.
582
595
 
583
596
  Default wiring guidance:
package/README.zh.md CHANGED
@@ -26,6 +26,11 @@
26
26
  (<code>docs/</code> 中的静态页,通过 GitHub Pages 发布;支持中英文切换)
27
27
  </p>
28
28
 
29
+ <p align="center">
30
+ <a href="https://botbotgo.github.io/agent-harness/development/">开发文档</a>
31
+ (多页面静态文档位于 <code>docs/development/</code>)
32
+ </p>
33
+
29
34
  <p align="center">
30
35
  <em
31
36
  >我们专注于 AI 解决方案。若有希望落地的产品想法,欢迎来信
@@ -142,6 +147,13 @@ AI 让 agent 逻辑、工具调用和工作流代码更容易生成,真正更
142
147
 
143
148
  边界说明见:
144
149
 
150
+ - `docs/development/index.html`
151
+ - `docs/development/getting-started.html`
152
+ - `docs/development/application-model.html`
153
+ - `docs/development/workspace-and-yaml.html`
154
+ - `docs/development/extensions.html`
155
+ - `docs/development/runtime-operations.html`
156
+ - `docs/development/testing-and-release.html`
145
157
  - `docs/upstream-feature-matrix.md`
146
158
  - `docs/product-boundary.md`
147
159
  - `docs/runtime-blueprint-assessment.md`
@@ -542,6 +554,7 @@ await stop(runtime);
542
554
 
543
555
  `resources/tools/` 下的工作区本地工具模块应统一用 `tool({...})` 导出。
544
556
  不支持历史/兼容写法,任何不带该导出形式的工具模块都会在工作区加载时被拒绝。
557
+ 本地 function tool 如果在模块里声明了 schema,runtime governance 会直接把该模块 schema 视为事实来源;不需要为了 schema-bound 元数据再额外复制一份 YAML `inputSchema.ref`。
545
558
  若本地工具使用 Zod schema,请让工作区或隔离的 `resources` 包统一使用 `zod@^4`,避免 raw shape validator 与 runtime 解析落在不同 major 版本上。
546
559
 
547
560
  主要有三层配置:
@@ -83,6 +83,7 @@ export type ParsedToolObject = {
83
83
  config?: Record<string, unknown>;
84
84
  subprocess?: boolean;
85
85
  inputSchemaRef?: string;
86
+ hasModuleSchema?: boolean;
86
87
  embeddingModelRef?: string;
87
88
  backendOperation?: string;
88
89
  mcpRef?: string;
@@ -132,6 +133,7 @@ export type CompiledTool = {
132
133
  config?: Record<string, unknown>;
133
134
  subprocess?: boolean;
134
135
  inputSchemaRef?: string;
136
+ hasModuleSchema?: boolean;
135
137
  embeddingModelRef?: string;
136
138
  backendOperation?: string;
137
139
  mcpRef?: string;
@@ -124,6 +124,7 @@ registerToolKind({
124
124
  config: tool.config,
125
125
  subprocess: tool.subprocess,
126
126
  inputSchemaRef: tool.inputSchemaRef,
127
+ hasModuleSchema: tool.hasModuleSchema,
127
128
  embeddingModelRef: tool.embeddingModelRef,
128
129
  bundleRefs: [],
129
130
  hitl: tool.hitl
@@ -158,6 +159,7 @@ registerToolKind({
158
159
  config: tool.config,
159
160
  subprocess: tool.subprocess,
160
161
  inputSchemaRef: tool.inputSchemaRef,
162
+ hasModuleSchema: tool.hasModuleSchema,
161
163
  embeddingModelRef: tool.embeddingModelRef,
162
164
  backendOperation: tool.backendOperation,
163
165
  bundleRefs: [],
@@ -193,6 +195,7 @@ registerToolKind({
193
195
  config: tool.config,
194
196
  subprocess: tool.subprocess,
195
197
  inputSchemaRef: tool.inputSchemaRef,
198
+ hasModuleSchema: tool.hasModuleSchema,
196
199
  embeddingModelRef: tool.embeddingModelRef,
197
200
  mcpRef: tool.mcpRef,
198
201
  bundleRefs: [],
@@ -234,6 +237,7 @@ registerToolKind({
234
237
  config: tool.config,
235
238
  subprocess: tool.subprocess,
236
239
  inputSchemaRef: tool.inputSchemaRef,
240
+ hasModuleSchema: tool.hasModuleSchema,
237
241
  embeddingModelRef: tool.embeddingModelRef,
238
242
  bundleRefs: [],
239
243
  hitl: tool.hitl
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.161";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.163";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.161";
1
+ export const AGENT_HARNESS_VERSION = "0.0.163";
@@ -1,6 +1,7 @@
1
1
  import { resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout } from "../adapter/resilience.js";
2
2
  import { toolRequiresRuntimeApproval } from "../adapter/tool/tool-hitl.js";
3
3
  import { getBindingPrimaryTools } from "../support/compiled-binding.js";
4
+ import { compiledToolHasInputSchema } from "./tool-schema.js";
4
5
  export function getWorkspaceBinding(workspace, agentId) {
5
6
  return workspace.bindings.get(agentId);
6
7
  }
@@ -29,7 +30,7 @@ export function projectBindingToolExecutionPolicy(binding) {
29
30
  toolId: tool.id,
30
31
  name: tool.name,
31
32
  retryable: tool.retryable === true,
32
- hasInputSchema: typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0,
33
+ hasInputSchema: compiledToolHasInputSchema(tool),
33
34
  requiresApproval: toolRequiresRuntimeApproval(tool),
34
35
  }));
35
36
  const retryableToolCount = projectedTools.filter((tool) => tool.retryable).length;
@@ -1,5 +1,6 @@
1
1
  import { getBindingPrimaryTools } from "../../support/compiled-binding.js";
2
2
  import { toolRequiresRuntimeApproval } from "../../adapter/tool/tool-hitl.js";
3
+ import { compiledToolHasInputSchema } from "../tool-schema.js";
3
4
  const WRITE_LIKE_PATTERN = /\b(write|edit|delete|create|update|append|insert|push|commit|publish|send|post|apply|merge|sync|upload|save)\b/i;
4
5
  function inputHints(binding, tool) {
5
6
  const hints = new Set();
@@ -173,7 +174,7 @@ export function buildRuntimeGovernanceBundles(binding) {
173
174
  }),
174
175
  requiresApproval,
175
176
  approvalPolicy: tool.hitl?.enabled === true ? "explicit-hitl" : requiresApproval ? "runtime-default" : "none",
176
- hasInputSchema: typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0,
177
+ hasInputSchema: compiledToolHasInputSchema(tool),
177
178
  inputRiskHints: inputHints(binding, tool),
178
179
  };
179
180
  })));
@@ -0,0 +1,2 @@
1
+ import type { CompiledTool } from "../../contracts/types.js";
2
+ export declare function compiledToolHasInputSchema(tool: Pick<CompiledTool, "inputSchemaRef" | "hasModuleSchema">): boolean;
@@ -0,0 +1,3 @@
1
+ export function compiledToolHasInputSchema(tool) {
2
+ return (typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0) || tool.hasModuleSchema === true;
3
+ }
@@ -4,6 +4,7 @@ export type LoadedToolModule = {
4
4
  implementationName: string;
5
5
  invoke: (input: unknown, context?: Record<string, unknown>) => Promise<unknown> | unknown;
6
6
  schema: ReturnType<typeof normalizeToolSchema>;
7
+ hasModuleSchema: boolean;
7
8
  description: string;
8
9
  retryable?: boolean;
9
10
  memory?: {
@@ -20,6 +20,7 @@ function loadToolObjectDefinition(imported, exportName) {
20
20
  implementationName: definition.name?.trim() || exportName,
21
21
  invoke: definition.invoke,
22
22
  schema: normalizeToolSchema(definition.schema),
23
+ hasModuleSchema: true,
23
24
  description: definition.description.trim(),
24
25
  retryable: definition.retryable === true,
25
26
  ...(definition.memory ? { memory: { ...definition.memory } } : {}),
@@ -4,7 +4,7 @@ import { readdir, readFile } from "node:fs/promises";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { resolveIsolatedResourceModulePath } from "../resource/isolation.js";
6
6
  import { isExternalSourceLocator, resolveResourcePackageRoot } from "../resource/sources.js";
7
- import { discoverToolModuleDefinitions, isSupportedToolModulePath } from "../tool-modules.js";
7
+ import { discoverToolModuleDefinitions, isSupportedToolModulePath, loadToolModuleDefinition } from "../tool-modules.js";
8
8
  import { fileExists } from "../utils/fs.js";
9
9
  import { readNamedYamlItems, readYamlItems, } from "./yaml-object-reader.js";
10
10
  export { normalizeYamlItem, readYamlItems } from "./yaml-object-reader.js";
@@ -633,12 +633,22 @@ async function readModuleToolItems(root) {
633
633
  if (inferredType === "function" && !discoveredPath) {
634
634
  throw new Error(`Module tool ${workspaceObject.id} must define implementation.path or provide index.mjs|index.js|index.cjs`);
635
635
  }
636
+ const implementationName = typeof normalizedItem.implementationName === "string" && normalizedItem.implementationName.trim().length > 0
637
+ ? normalizedItem.implementationName.trim()
638
+ : typeof implementation?.export === "string" && implementation.export.trim().length > 0
639
+ ? implementation.export.trim()
640
+ : workspaceObject.id;
641
+ const schemaMetadata = inferredType === "function" && discoveredPath
642
+ ? await readModuleToolSchemaMetadata({
643
+ sourcePath: discoveredPath,
644
+ implementationName,
645
+ })
646
+ : { hasModuleSchema: false };
636
647
  records.push({
637
648
  item: {
638
649
  ...normalizedItem,
639
- ...(typeof implementation?.export === "string" && !normalizedItem.implementationName
640
- ? { implementationName: implementation.export }
641
- : {}),
650
+ ...(typeof implementation?.export === "string" && !normalizedItem.implementationName ? { implementationName } : {}),
651
+ ...(schemaMetadata.hasModuleSchema ? { hasModuleSchema: true } : {}),
642
652
  },
643
653
  sourcePath: discoveredPath ?? sourcePath,
644
654
  });
@@ -646,6 +656,32 @@ async function readModuleToolItems(root) {
646
656
  }
647
657
  return records;
648
658
  }
659
+ function findToolPackageRoot(startPath) {
660
+ let current = path.dirname(startPath);
661
+ for (;;) {
662
+ const packageJsonPath = path.join(current, "package.json");
663
+ if (existsSync(packageJsonPath)) {
664
+ return current;
665
+ }
666
+ const parent = path.dirname(current);
667
+ if (parent === current) {
668
+ return path.dirname(startPath);
669
+ }
670
+ current = parent;
671
+ }
672
+ }
673
+ async function readModuleToolSchemaMetadata(input) {
674
+ if (!isSupportedToolModulePath(input.sourcePath)) {
675
+ return { hasModuleSchema: false };
676
+ }
677
+ const packageRoot = findToolPackageRoot(input.sourcePath);
678
+ const isolatedSourcePath = await resolveIsolatedResourceModulePath(packageRoot, input.sourcePath);
679
+ const imported = await import(pathToFileURL(isolatedSourcePath).href);
680
+ const definition = loadToolModuleDefinition(imported, input.implementationName);
681
+ return {
682
+ hasModuleSchema: definition.hasModuleSchema,
683
+ };
684
+ }
649
685
  async function loadModuleObjectsForRoot(root, mergedObjects) {
650
686
  for (const { item, sourcePath } of await readModuleToolItems(root)) {
651
687
  const workspaceObject = parseWorkspaceObject(item, sourcePath);
@@ -728,6 +764,7 @@ export async function readToolModuleItems(root) {
728
764
  name: definition.implementationName,
729
765
  description: definition.description,
730
766
  implementationName: definition.implementationName,
767
+ hasModuleSchema: definition.hasModuleSchema,
731
768
  ...(definition.retryable !== undefined ? { retryable: definition.retryable } : {}),
732
769
  ...(definition.memory ? { config: { memory: definition.memory } } : {}),
733
770
  },
@@ -269,6 +269,7 @@ export function parseToolObject(object) {
269
269
  : undefined),
270
270
  subprocess: value.subprocess === true,
271
271
  inputSchemaRef: typeof asObject(value.inputSchema)?.ref === "string" ? String(asObject(value.inputSchema)?.ref) : undefined,
272
+ hasModuleSchema: value.hasModuleSchema === true,
272
273
  embeddingModelRef: typeof value.embeddingModelRef === "string"
273
274
  ? value.embeddingModelRef
274
275
  : typeof value.embeddingModel === "string"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.162",
3
+ "version": "0.0.164",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",