Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,742 changes: 143 additions & 2,599 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,11 @@
"engines": {
"node": ">=20.0.0",
"npm": ">=9.0.0"
},
"overrides": {
"zod": "^4.4.3",
"@anthropic-ai/claude-agent-sdk": {
"zod": "^4.4.3"
}
}
}
2 changes: 1 addition & 1 deletion packages/autonav/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"ora": "^9.4.1",
"react": "^18.3.1",
"tar": "^7.5.19",
"zod": "^3.24.1"
"zod": "^4.4.3"
},
"devDependencies": {
"@testing-library/react": "^14.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/autonav/src/harness/claude-code-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ export class ClaudeCodeHarness implements Harness {
createToolServer(name: string, tools: ToolDefinition[]): { server: unknown } {
const sdkTools = tools.map((td) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tool(td.name, td.description, td.inputSchema, ((args: any) => td.handler(args)) as any)
tool(td.name, td.description, td.inputSchema as any, ((args: any) => td.handler(args)) as any)
);
const server = createSdkMcpServer({
name,
Expand Down
2 changes: 1 addition & 1 deletion packages/autonav/src/mend/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export async function checkNavigatorHealth(navPath: string): Promise<MendResult>
check: "config.json schema",
status: "fail",
message: "config.json schema validation failed",
details: parseResult.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join("; "),
details: parseResult.error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join("; "),
autoFixable: false,
});
} else {
Expand Down
2 changes: 1 addition & 1 deletion packages/autonav/src/plugins/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const PluginConfigFileSchema = z.record(
z.string(), // Plugin name
z.object({
enabled: z.boolean(),
config: z.record(z.unknown()).optional(),
config: z.record(z.string(), z.unknown()).optional(),
})
);

Expand Down
2 changes: 1 addition & 1 deletion packages/autonav/src/plugins/plugin-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const PluginsConfigSchema = z.record(
z.string(), // Plugin name
z.object({
enabled: z.boolean(),
config: z.record(z.unknown()).optional(), // Plugin-specific config
config: z.record(z.string(), z.unknown()).optional(), // Plugin-specific config
})
);

Expand Down
2 changes: 1 addition & 1 deletion packages/autonav/src/tools/self-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ This allows you to autonomously manage your own behavior based on user requests.
plugin: z.enum(CONFIGURABLE_PLUGINS).describe(
"The plugin to configure (slack, signal, github, or email)"
),
updates: z.record(z.unknown()).describe(
updates: z.record(z.string(), z.unknown()).describe(
`Configuration updates to apply. Common patterns:
- signal: { checkInSchedule: "custom", nextCheckIn: "2025-01-15T15:00:00Z", notificationTypes: ["urgent"] }
- slack: { channels: ["platform-team"], summaryFrequency: "weekly" }
Expand Down
2 changes: 1 addition & 1 deletion packages/communication-layer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"url": "https://github.com/terraboops/autonav/issues"
},
"dependencies": {
"zod": "^3.25.76"
"zod": "^4.4.3"
},
"devDependencies": {
"@types/node": "^20.0.0",
Expand Down
43 changes: 24 additions & 19 deletions packages/communication-layer/src/schemas/config-describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,57 +24,62 @@ interface FieldInfo {
// ── Schema analysis ─────────────────────────────────────────────────────────

function analyzeZodField(schema: z.ZodTypeAny): FieldInfo {
const def = schema._def as Record<string, unknown>;
const typeName = def.typeName as string;
// Zod 4 exposes the internal definition under `_zod.def` and uses lowercase
// `type` discriminators (e.g. "string", "optional") instead of `typeName`.
const def = (schema as unknown as { _zod: { def: Record<string, unknown> } })._zod.def;
const type = def.type as string;
// Descriptions now live in the global registry, surfaced via `.description`.
const ownDescription = (schema.description as string | undefined) || '';

// Unwrap wrapper types (order matters: optional/default/nullable are outermost)
if (typeName === 'ZodOptional') {
if (type === 'optional') {
const inner = analyzeZodField(def.innerType as z.ZodTypeAny);
inner.optional = true;
if (!inner.description && def.description) inner.description = def.description as string;
if (!inner.description && ownDescription) inner.description = ownDescription;
return inner;
}

if (typeName === 'ZodDefault') {
if (type === 'default') {
const inner = analyzeZodField(def.innerType as z.ZodTypeAny);
inner.optional = true; // has default → not required in JSON
inner.defaultValue = (def.defaultValue as () => unknown)();
if (!inner.description && def.description) inner.description = def.description as string;
// In Zod 4 `defaultValue` is the value itself (no longer a factory function).
inner.defaultValue = def.defaultValue;
if (!inner.description && ownDescription) inner.description = ownDescription;
return inner;
}

if (typeName === 'ZodNullable') {
if (type === 'nullable') {
const inner = analyzeZodField(def.innerType as z.ZodTypeAny);
inner.type += ' | null';
if (!inner.description && def.description) inner.description = def.description as string;
if (!inner.description && ownDescription) inner.description = ownDescription;
return inner;
}

// Base types
const description = (def.description as string) || '';
const description = ownDescription;

if (typeName === 'ZodString') {
if (type === 'string') {
return { type: 'string', description, optional: false };
}
if (typeName === 'ZodNumber') {
if (type === 'number') {
return { type: 'number', description, optional: false };
}
if (typeName === 'ZodBoolean') {
if (type === 'boolean') {
return { type: 'boolean', description, optional: false };
}
if (typeName === 'ZodEnum') {
if (type === 'enum') {
return {
type: 'enum',
description,
optional: false,
enumValues: def.values as string[],
enumValues: Object.values(def.entries as Record<string, string>),
};
}
if (typeName === 'ZodRecord') {
if (type === 'record') {
return { type: 'object (key-value pairs)', description, optional: false };
}
if (typeName === 'ZodArray') {
const itemType = def.type as z.ZodTypeAny;
if (type === 'array') {
const itemType = def.element as z.ZodTypeAny;
const itemInfo = analyzeZodField(itemType);
if (itemInfo.children) {
return {
Expand All @@ -86,7 +91,7 @@ function analyzeZodField(schema: z.ZodTypeAny): FieldInfo {
}
return { type: `${itemInfo.type}[]`, description, optional: false };
}
if (typeName === 'ZodObject') {
if (type === 'object') {
const shape = (schema as z.ZodObject<z.ZodRawShape>).shape;
const children: Record<string, FieldInfo> = {};
for (const [key, childField] of Object.entries(shape)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/communication-layer/src/schemas/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const SafeCommandSchema = z.string()
.min(1, 'Command cannot be empty')
.refine(
(cmd) => !DENIED_SANDBOX_COMMANDS.has(cmd.toLowerCase()),
(cmd) => ({ message: `Command "${cmd}" is denied — it could bypass sandbox enforcement` })
'Command is denied — it could bypass sandbox enforcement'
)
.refine(
(cmd) => !cmd.includes('/'),
Expand Down Expand Up @@ -111,7 +111,7 @@ export const NavigatorConfigSchema = z.object({
* Additional configuration options
* For future extensions without breaking changes
*/
metadata: z.record(z.unknown()).optional().describe('Additional metadata'),
metadata: z.record(z.string(), z.unknown()).optional().describe('Additional metadata'),

/**
* Knowledge pack metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const NavigatorResponseSchema = z.object({
* Additional metadata for future extensions
* Examples: search strategy used, tokens consumed, execution time
*/
metadata: z.record(z.unknown()).optional(),
metadata: z.record(z.string(), z.unknown()).optional(),

/**
* Timestamp when the response was generated
Expand Down
2 changes: 1 addition & 1 deletion packages/communication-layer/src/schemas/plugin-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function validatePluginConfig(config: unknown): {

return {
valid: false,
errors: result.error.errors.map((e: { path: Array<string | number>; message: string }) =>
errors: result.error.issues.map((e: { path: PropertyKey[]; message: string }) =>
`${e.path.join('.')}: ${e.message}`
),
};
Expand Down
2 changes: 1 addition & 1 deletion packages/knowledge-pack-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"license": "TBD",
"dependencies": {
"express": "^5.2.1",
"zod": "^3.22.4"
"zod": "^4.4.3"
},
"devDependencies": {
"@types/express": "^5.0.6",
Expand Down
Loading