@easynet/agent-runtime 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/.github/workflows/ci.yml +9 -24
- package/.github/workflows/release.yml +14 -35
- package/agent-runtime/.github/workflows/ci.yml +69 -0
- package/agent-runtime/.github/workflows/release.yml +118 -0
- package/agent-runtime/.releaserc.cjs +26 -0
- package/agent-runtime/config/agent.deep.yaml +25 -0
- package/agent-runtime/config/agent.react.yaml +24 -0
- package/agent-runtime/example/basic-usage.ts +49 -0
- package/agent-runtime/package-lock.json +7740 -0
- package/agent-runtime/package.json +49 -0
- package/agent-runtime/pnpm-lock.yaml +3712 -0
- package/agent-runtime/scripts/resolve-deps.js +54 -0
- package/agent-runtime/src/agents/deep-agent.ts +165 -0
- package/agent-runtime/src/agents/react-agent.helpers.ts +227 -0
- package/agent-runtime/src/agents/react-agent.ts +584 -0
- package/{src → agent-runtime/src/agents}/sub-agent.ts +2 -2
- package/agent-runtime/src/cli/args.ts +15 -0
- package/agent-runtime/src/cli/event-listener.ts +162 -0
- package/agent-runtime/src/cli/interactive.ts +144 -0
- package/agent-runtime/src/cli/runtime.ts +31 -0
- package/agent-runtime/src/cli/spinner.ts +23 -0
- package/agent-runtime/src/cli/terminal-render.ts +322 -0
- package/agent-runtime/src/cli/types.ts +33 -0
- package/agent-runtime/src/cli.ts +134 -0
- package/agent-runtime/src/config/helpers.ts +179 -0
- package/agent-runtime/src/config/index.ts +245 -0
- package/agent-runtime/src/config/types.ts +62 -0
- package/agent-runtime/src/core/context.ts +266 -0
- package/agent-runtime/src/index.ts +55 -0
- package/agent-runtime/tsconfig.json +18 -0
- package/apps/imessagebot/README.md +38 -0
- package/apps/imessagebot/config/.agent/cache/easynet/agent-tool-buildin/0.0.45/README.md +33 -0
- package/apps/imessagebot/config/.agent/cache/easynet/agent-tool-buildin/0.0.45/package-lock.json +15257 -0
- package/apps/imessagebot/config/.agent/cache/easynet/agent-tool-buildin/0.0.45/package.json +55 -0
- package/apps/imessagebot/config/agents/deep/agent.yaml +31 -0
- package/apps/imessagebot/config/agents/react/agent.yaml +58 -0
- package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.43/README.md +33 -0
- package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.43/package-lock.json +15457 -0
- package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.43/package.json +55 -0
- package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.46/README.md +33 -0
- package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.46/package-lock.json +15257 -0
- package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.46/package.json +62 -0
- package/apps/imessagebot/config/agents/shared/memory.yaml +31 -0
- package/apps/imessagebot/config/agents/shared/model.yaml +23 -0
- package/apps/imessagebot/config/agents/shared/tool.yaml +13 -0
- package/apps/imessagebot/config/app.yaml +14 -0
- package/apps/imessagebot/package-lock.json +53695 -0
- package/apps/imessagebot/package.json +41 -0
- package/apps/imessagebot/pnpm-lock.yaml +1589 -0
- package/apps/imessagebot/scripts/resolve-deps.js +41 -0
- package/apps/imessagebot/scripts/test-llm.mjs +27 -0
- package/apps/imessagebot/scripts/validate-tools-config.mjs +174 -0
- package/apps/imessagebot/src/config.ts +76 -0
- package/apps/imessagebot/src/context.ts +35 -0
- package/apps/imessagebot/src/index.ts +17 -0
- package/apps/imessagebot/tsconfig.json +18 -0
- package/apps/itermbot/.github/workflows/ci.yml +61 -0
- package/apps/itermbot/.github/workflows/release.yml +80 -0
- package/apps/itermbot/.releaserc.cjs +26 -0
- package/apps/itermbot/README.md +82 -0
- package/apps/itermbot/config/app.yaml +29 -0
- package/apps/itermbot/config/tsconfig.json +18 -0
- package/apps/itermbot/macos_disk_usage_agent_plan.md +244 -0
- package/apps/itermbot/package-lock.json +53697 -0
- package/apps/itermbot/package.json +57 -0
- package/apps/itermbot/pnpm-lock.yaml +3966 -0
- package/apps/itermbot/scripts/patch-buildin-cache.sh +25 -0
- package/apps/itermbot/scripts/resolve-deps.js +41 -0
- package/apps/itermbot/scripts/test-llm.mjs +32 -0
- package/apps/itermbot/skills/command-explain-and-guard/SKILL.md +39 -0
- package/apps/itermbot/skills/command-explain-and-guard/handler.js +86 -0
- package/apps/itermbot/skills/disk-usage-investigate/SKILL.md +44 -0
- package/apps/itermbot/skills/disk-usage-investigate/handler.js +12 -0
- package/apps/itermbot/skills/gpu-ssh-monitor/SKILL.md +64 -0
- package/apps/itermbot/skills/repo-triage/SKILL.md +40 -0
- package/apps/itermbot/skills/repo-triage/handler.js +56 -0
- package/apps/itermbot/skills/test-failure-diagnose/SKILL.md +43 -0
- package/apps/itermbot/skills/test-failure-diagnose/handler.js +107 -0
- package/apps/itermbot/src/config.ts +95 -0
- package/apps/itermbot/src/context.ts +35 -0
- package/apps/itermbot/src/index.ts +223 -0
- package/apps/itermbot/src/iterm/session-hint.ts +40 -0
- package/apps/itermbot/src/iterm/target-routing.ts +419 -0
- package/apps/itermbot/src/startup/colors.ts +317 -0
- package/apps/itermbot/src/startup/diagnostics.ts +97 -0
- package/apps/itermbot/src/startup/ui.ts +141 -0
- package/config/agent.deep.yaml +25 -0
- package/config/agent.react.yaml +24 -0
- package/dist/agents/deep-agent.d.ts +37 -0
- package/dist/agents/deep-agent.d.ts.map +1 -0
- package/dist/agents/deep-agent.js +115 -0
- package/dist/agents/deep-agent.js.map +1 -0
- package/dist/agents/react-agent.d.ts +40 -0
- package/dist/agents/react-agent.d.ts.map +1 -0
- package/dist/agents/react-agent.helpers.d.ts +40 -0
- package/dist/agents/react-agent.helpers.d.ts.map +1 -0
- package/dist/agents/react-agent.helpers.js +196 -0
- package/dist/agents/react-agent.helpers.js.map +1 -0
- package/dist/agents/react-agent.js +400 -0
- package/dist/agents/react-agent.js.map +1 -0
- package/dist/agents/sub-agent.d.ts +34 -0
- package/dist/agents/sub-agent.d.ts.map +1 -0
- package/dist/agents/sub-agent.js +53 -0
- package/dist/agents/sub-agent.js.map +1 -0
- package/dist/cli/args.d.ts +8 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +9 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/event-listener.d.ts +3 -0
- package/dist/cli/event-listener.d.ts.map +1 -0
- package/dist/cli/event-listener.js +131 -0
- package/dist/cli/event-listener.js.map +1 -0
- package/dist/cli/interactive.d.ts +4 -0
- package/dist/cli/interactive.d.ts.map +1 -0
- package/dist/cli/interactive.js +118 -0
- package/dist/cli/interactive.js.map +1 -0
- package/dist/cli/runtime.d.ts +8 -0
- package/dist/cli/runtime.d.ts.map +1 -0
- package/dist/cli/runtime.js +27 -0
- package/dist/cli/runtime.js.map +1 -0
- package/dist/cli/spinner.d.ts +2 -0
- package/dist/cli/spinner.d.ts.map +1 -0
- package/dist/cli/spinner.js +22 -0
- package/dist/cli/spinner.js.map +1 -0
- package/dist/cli/terminal-render.d.ts +7 -0
- package/dist/cli/terminal-render.d.ts.map +1 -0
- package/dist/cli/terminal-render.js +282 -0
- package/dist/cli/terminal-render.js.map +1 -0
- package/dist/cli/types.d.ts +29 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +3 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli.d.ts +4 -41
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +84 -588
- package/dist/cli.js.map +1 -1
- package/dist/config/helpers.d.ts +6 -0
- package/dist/config/helpers.d.ts.map +1 -0
- package/dist/config/helpers.js +164 -0
- package/dist/config/helpers.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +160 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +57 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/context.d.ts +8 -69
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +44 -24
- package/dist/context.js.map +1 -1
- package/dist/core/context.d.ts +66 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +149 -0
- package/dist/core/context.js.map +1 -0
- package/dist/deep-agent.d.ts +5 -2
- package/dist/deep-agent.d.ts.map +1 -1
- package/dist/deep-agent.js +44 -11
- package/dist/deep-agent.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/middleware/malformed-tool-call-middleware.d.ts +8 -0
- package/dist/middleware/malformed-tool-call-middleware.d.ts.map +1 -0
- package/dist/middleware/malformed-tool-call-middleware.js +191 -0
- package/dist/middleware/malformed-tool-call-middleware.js.map +1 -0
- package/dist/react-agent.d.ts +2 -2
- package/dist/react-agent.d.ts.map +1 -1
- package/dist/react-agent.js +28 -9
- package/dist/react-agent.js.map +1 -1
- package/package.json +1 -1
- package/scripts/resolve-deps.js +54 -0
- package/src/agents/deep-agent.ts +165 -0
- package/src/agents/react-agent.helpers.ts +227 -0
- package/src/agents/react-agent.ts +584 -0
- package/src/agents/sub-agent.ts +82 -0
- package/src/cli/args.ts +15 -0
- package/src/cli/event-listener.ts +162 -0
- package/src/cli/interactive.ts +144 -0
- package/src/cli/runtime.ts +31 -0
- package/src/cli/spinner.ts +23 -0
- package/src/cli/terminal-render.ts +322 -0
- package/src/cli/types.ts +33 -0
- package/src/cli.ts +91 -702
- package/src/config/helpers.ts +179 -0
- package/src/config/index.ts +245 -0
- package/src/config/types.ts +62 -0
- package/src/core/context.ts +266 -0
- package/src/index.ts +13 -11
- package/src/middleware/malformed-tool-call-middleware.ts +239 -0
- package/src/types/markdown-it-terminal.d.ts +4 -0
- package/src/types/marked-terminal.d.ts +16 -0
- package/dist/config.d.ts +0 -86
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -84
- package/dist/config.js.map +0 -1
- package/src/config.ts +0 -177
- package/src/context.ts +0 -247
- package/src/deep-agent.ts +0 -104
- package/src/react-agent.ts +0 -576
- /package/{src → agent-runtime/src/middleware}/malformed-tool-call-middleware.ts +0 -0
- /package/{src → agent-runtime/src/types}/markdown-it-terminal.d.ts +0 -0
- /package/{src → agent-runtime/src/types}/marked-terminal.d.ts +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AgentEventListener } from "@easynet/agent-common";
|
|
2
|
+
import type { BotContext } from "../core/context.js";
|
|
3
|
+
|
|
4
|
+
export const REACT = "react" as const;
|
|
5
|
+
export const DEEP = "deep" as const;
|
|
6
|
+
|
|
7
|
+
export type AgentKind = typeof REACT | typeof DEEP;
|
|
8
|
+
|
|
9
|
+
export interface AppCliUiOptions {
|
|
10
|
+
userLabel?: string;
|
|
11
|
+
assistantLabel?: string;
|
|
12
|
+
useColor?: boolean;
|
|
13
|
+
renderMarkdown?: boolean;
|
|
14
|
+
echoUserQuestion?: boolean;
|
|
15
|
+
loadingText?: string | false;
|
|
16
|
+
loadingSpinner?: boolean;
|
|
17
|
+
readyText?: string | false;
|
|
18
|
+
interactiveIntro?: string | false;
|
|
19
|
+
processingSpinner?: boolean;
|
|
20
|
+
processingText?: string | false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AppCliOptions {
|
|
24
|
+
appName: string;
|
|
25
|
+
createBotContext: () => Promise<BotContext>;
|
|
26
|
+
interactiveCommands?: Record<string, InteractiveCommandHandler>;
|
|
27
|
+
eventListener?: AgentEventListener | AgentEventListener[];
|
|
28
|
+
onReady?: (ctx: BotContext) => void | Promise<void>;
|
|
29
|
+
onShutdown?: (ctx: BotContext) => void;
|
|
30
|
+
ui?: AppCliUiOptions;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type InteractiveCommandHandler = (ctx: BotContext) => void | Promise<void>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI runner for agent apps.
|
|
3
|
+
* Provides: arg parsing, single-shot mode, interactive REPL, event logging.
|
|
4
|
+
*/
|
|
5
|
+
import { createConsoleAgentEventListener } from "@easynet/agent-common";
|
|
6
|
+
import { parseArgs } from "./cli/args.js";
|
|
7
|
+
import { createStructuredRunEventListener } from "./cli/event-listener.js";
|
|
8
|
+
import { interactive } from "./cli/interactive.js";
|
|
9
|
+
import { readDefaultAgentKindFromConfig, runOne } from "./cli/runtime.js";
|
|
10
|
+
import { startLoadingSpinner } from "./cli/spinner.js";
|
|
11
|
+
import { renderForTerminal } from "./cli/terminal-render.js";
|
|
12
|
+
import { REACT, type AgentKind, type AppCliOptions, type AppCliUiOptions } from "./cli/types.js";
|
|
13
|
+
|
|
14
|
+
export type { AppCliOptions, AppCliUiOptions };
|
|
15
|
+
export { createStructuredRunEventListener };
|
|
16
|
+
|
|
17
|
+
function createExitHandler(
|
|
18
|
+
appName: string,
|
|
19
|
+
onShutdown: AppCliOptions["onShutdown"],
|
|
20
|
+
ctx: Awaited<ReturnType<AppCliOptions["createBotContext"]>>,
|
|
21
|
+
): (code: number) => never {
|
|
22
|
+
let didCleanup = false;
|
|
23
|
+
|
|
24
|
+
const cleanup = () => {
|
|
25
|
+
if (didCleanup) return;
|
|
26
|
+
didCleanup = true;
|
|
27
|
+
try {
|
|
28
|
+
onShutdown?.(ctx);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
console.error(`${appName}: onShutdown hook failed:`, err instanceof Error ? err.message : err);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
process.once("exit", cleanup);
|
|
35
|
+
const exitApp = (code: number): never => {
|
|
36
|
+
cleanup();
|
|
37
|
+
process.exit(code);
|
|
38
|
+
};
|
|
39
|
+
process.once("SIGINT", () => exitApp(130));
|
|
40
|
+
process.once("SIGTERM", () => exitApp(143));
|
|
41
|
+
return exitApp;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function subscribeEventListeners(options: AppCliOptions, ctx: Awaited<ReturnType<AppCliOptions["createBotContext"]>>): void {
|
|
45
|
+
if (process.env.AGENT_EVENT_STDERR === "1") {
|
|
46
|
+
ctx.events.subscribe(createConsoleAgentEventListener());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const listeners = Array.isArray(options.eventListener)
|
|
50
|
+
? options.eventListener
|
|
51
|
+
: options.eventListener
|
|
52
|
+
? [options.eventListener]
|
|
53
|
+
: [];
|
|
54
|
+
for (const listener of listeners) {
|
|
55
|
+
ctx.events.subscribe(listener);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function runOnReady(options: AppCliOptions, appName: string, ctx: Awaited<ReturnType<AppCliOptions["createBotContext"]>>): Promise<void> {
|
|
60
|
+
if (!options.onReady) return;
|
|
61
|
+
try {
|
|
62
|
+
await options.onReady(ctx);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error(`${appName}: onReady hook failed:`, err instanceof Error ? err.message : err);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function createContextWithLoading(options: AppCliOptions): Promise<Awaited<ReturnType<AppCliOptions["createBotContext"]>>> {
|
|
69
|
+
const loadingText = options.ui?.loadingText ?? `${options.appName}: loading config, LLM, memory, tools...`;
|
|
70
|
+
const useLoadingSpinner = options.ui?.loadingSpinner ?? false;
|
|
71
|
+
let stopLoadingSpinner: (() => void) | null = null;
|
|
72
|
+
|
|
73
|
+
if (loadingText !== false) {
|
|
74
|
+
if (useLoadingSpinner && Boolean(process.stderr.isTTY)) {
|
|
75
|
+
stopLoadingSpinner = startLoadingSpinner(loadingText);
|
|
76
|
+
} else {
|
|
77
|
+
console.error(loadingText);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const ctx = await options.createBotContext();
|
|
82
|
+
stopLoadingSpinner?.();
|
|
83
|
+
return ctx;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function printReady(options: AppCliOptions, kind: AgentKind): void {
|
|
87
|
+
const agentLabel = kind === REACT ? "ReAct (LangChain)" : "Deep (DeepAgents)";
|
|
88
|
+
const readyText = options.ui?.readyText ?? `Ready. Agent: ${agentLabel}`;
|
|
89
|
+
if (readyText !== false) {
|
|
90
|
+
console.error(readyText);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function resolveAgentKind(parsed: ReturnType<typeof parseArgs>, ctx: Awaited<ReturnType<AppCliOptions["createBotContext"]>>): AgentKind {
|
|
95
|
+
if (parsed.explicitKind) return parsed.kind;
|
|
96
|
+
return readDefaultAgentKindFromConfig(ctx) ?? parsed.kind;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function runSingleQuery(
|
|
100
|
+
options: AppCliOptions,
|
|
101
|
+
ctx: Awaited<ReturnType<AppCliOptions["createBotContext"]>>,
|
|
102
|
+
kind: AgentKind,
|
|
103
|
+
query: string,
|
|
104
|
+
): Promise<void> {
|
|
105
|
+
const text = await runOne(ctx, kind, query);
|
|
106
|
+
const useColor = options.ui?.useColor ?? (Boolean(process.stdout.isTTY) && !process.env.NO_COLOR);
|
|
107
|
+
const renderMarkdown = options.ui?.renderMarkdown ?? true;
|
|
108
|
+
console.log(renderForTerminal(text, { renderMarkdown, useColor }));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function runAppCli(options: AppCliOptions): void {
|
|
112
|
+
const main = async () => {
|
|
113
|
+
const parsed = parseArgs();
|
|
114
|
+
const ctx = await createContextWithLoading(options);
|
|
115
|
+
const kind = resolveAgentKind(parsed, ctx);
|
|
116
|
+
const exitApp = createExitHandler(options.appName, options.onShutdown, ctx);
|
|
117
|
+
|
|
118
|
+
subscribeEventListeners(options, ctx);
|
|
119
|
+
await runOnReady(options, options.appName, ctx);
|
|
120
|
+
printReady(options, kind);
|
|
121
|
+
|
|
122
|
+
if (parsed.query) {
|
|
123
|
+
await runSingleQuery(options, ctx, kind, parsed.query);
|
|
124
|
+
exitApp(0);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
await interactive(ctx, kind, options, exitApp);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
main().catch((err) => {
|
|
131
|
+
console.error(err);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { deepMerge, hydrateNamedScopedDefaults, loadModuleConfig } from "@easynet/agent-common";
|
|
5
|
+
import { normalizeSkillConfig, resolveSkillRuntimeDefaults as resolveSkillRuntimeDefaultsFromModule } from "@easynet/agent-skill";
|
|
6
|
+
import { normalizeAgentToolConfigRef } from "@easynet/agent-tool";
|
|
7
|
+
import type { AgentProfileConfig, AgentMemoryProfileRef, AgentMemoryRuntimeRef } from "./types.js";
|
|
8
|
+
|
|
9
|
+
const RUNTIME_CONFIG_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../../config");
|
|
10
|
+
|
|
11
|
+
let defaultProfilesPromise: Promise<Record<string, AgentProfileConfig>> | null = null;
|
|
12
|
+
|
|
13
|
+
function asMemoryObject(input: unknown): Record<string, unknown> | undefined {
|
|
14
|
+
return typeof input === "object" && input !== null ? (input as Record<string, unknown>) : undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function normalizeAgentMemoryRuntimeRef(raw: unknown): Partial<AgentMemoryRuntimeRef> {
|
|
18
|
+
const obj = asMemoryObject(raw);
|
|
19
|
+
if (!obj) return {};
|
|
20
|
+
const out: Partial<AgentMemoryRuntimeRef> = {};
|
|
21
|
+
if (obj.namespace_mode === "thread" || obj.namespace_mode === "fixed") out.namespace_mode = obj.namespace_mode;
|
|
22
|
+
if (typeof obj.namespace === "string") out.namespace = obj.namespace;
|
|
23
|
+
if (typeof obj.top_k === "number") out.top_k = obj.top_k;
|
|
24
|
+
if (typeof obj.budget_tokens === "number") out.budget_tokens = obj.budget_tokens;
|
|
25
|
+
if (typeof obj.auto_write === "boolean") out.auto_write = obj.auto_write;
|
|
26
|
+
if (obj.auto_write_scope === "thread" || obj.auto_write_scope === "cross_thread" || obj.auto_write_scope === "knowledge" || obj.auto_write_scope === "auto") out.auto_write_scope = obj.auto_write_scope;
|
|
27
|
+
if (typeof obj.auto_write_max_chars === "number") out.auto_write_max_chars = obj.auto_write_max_chars;
|
|
28
|
+
if (typeof obj.auto_write_user === "boolean") out.auto_write_user = obj.auto_write_user;
|
|
29
|
+
if (typeof obj.auto_write_assistant === "boolean") out.auto_write_assistant = obj.auto_write_assistant;
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeAgentMemoryProfileRef(raw: unknown): Partial<AgentMemoryProfileRef> {
|
|
34
|
+
if (typeof raw === "string" && raw.trim().length > 0) return { ref: raw.trim() };
|
|
35
|
+
const obj = asMemoryObject(raw);
|
|
36
|
+
if (!obj) return {};
|
|
37
|
+
const runtime = normalizeAgentMemoryRuntimeRef(obj);
|
|
38
|
+
const out: Partial<AgentMemoryProfileRef> = { ...runtime };
|
|
39
|
+
if (typeof obj.ref === "string" && obj.ref.trim().length > 0) out.ref = obj.ref.trim();
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function resolveAgentMemoryRuntimeDefaultsFromModule(
|
|
44
|
+
memoryRef: string,
|
|
45
|
+
appRoot: string,
|
|
46
|
+
): Promise<Partial<AgentMemoryRuntimeRef>> {
|
|
47
|
+
const common = await import("@easynet/agent-common");
|
|
48
|
+
const loadModuleConfigFn = (common as {
|
|
49
|
+
loadModuleConfig?: <TConfig>(options: { path: string; appRoot: string; unwrapSpec: boolean; fallback: TConfig }) => Promise<TConfig>;
|
|
50
|
+
}).loadModuleConfig;
|
|
51
|
+
const raw: Record<string, unknown> = typeof loadModuleConfigFn === "function"
|
|
52
|
+
? await loadModuleConfigFn<Record<string, unknown>>({ path: memoryRef, appRoot, unwrapSpec: true, fallback: {} }) as Record<string, unknown>
|
|
53
|
+
: {};
|
|
54
|
+
const rootRuntime = normalizeAgentMemoryRuntimeRef(asMemoryObject(raw.runtime));
|
|
55
|
+
const memoryRuntime = normalizeAgentMemoryRuntimeRef(asMemoryObject(asMemoryObject(raw.memory)?.runtime));
|
|
56
|
+
return { ...rootRuntime, ...memoryRuntime };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function normalizeAgentModelConfigRef(raw: unknown): { ref?: string } {
|
|
60
|
+
if (typeof raw === "string" && raw.trim().length > 0) return { ref: raw.trim() };
|
|
61
|
+
if (typeof raw !== "object" || raw === null) return {};
|
|
62
|
+
const ref = (raw as { ref?: unknown }).ref;
|
|
63
|
+
if (typeof ref === "string" && ref.trim().length > 0) return { ref: ref.trim() };
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function discoverDefaultAgentProfileFiles(): Promise<Record<string, string>> {
|
|
68
|
+
try {
|
|
69
|
+
const entries = await readdir(RUNTIME_CONFIG_DIR, { withFileTypes: true });
|
|
70
|
+
return Object.fromEntries(
|
|
71
|
+
entries
|
|
72
|
+
.filter((entry) => entry.isFile())
|
|
73
|
+
.map((entry) => {
|
|
74
|
+
const match = /^agent\.(.+)\.ya?ml$/i.exec(entry.name);
|
|
75
|
+
if (!match) return null;
|
|
76
|
+
return [match[1], resolve(RUNTIME_CONFIG_DIR, entry.name)] as const;
|
|
77
|
+
})
|
|
78
|
+
.filter((item): item is readonly [string, string] => item !== null),
|
|
79
|
+
);
|
|
80
|
+
} catch {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function normalizeProfileConfig(
|
|
86
|
+
raw: Record<string, unknown> | undefined,
|
|
87
|
+
base?: AgentProfileConfig
|
|
88
|
+
): AgentProfileConfig {
|
|
89
|
+
const merged: AgentProfileConfig = deepMerge({} as AgentProfileConfig, base ?? {});
|
|
90
|
+
if (!raw) return merged;
|
|
91
|
+
|
|
92
|
+
const models = normalizeAgentModelConfigRef(raw.models);
|
|
93
|
+
if (Object.keys(models).length > 0) merged.models = { ...(merged.models ?? {}), ...models };
|
|
94
|
+
|
|
95
|
+
const memory = normalizeAgentMemoryProfileRef(raw.memory);
|
|
96
|
+
if (Object.keys(memory).length > 0) merged.memory = { ...(merged.memory ?? {}), ...memory };
|
|
97
|
+
|
|
98
|
+
const tools = normalizeAgentToolConfigRef(raw.tools);
|
|
99
|
+
if (Object.keys(tools).length > 0) merged.tools = { ...(merged.tools ?? {}), ...tools };
|
|
100
|
+
|
|
101
|
+
const skills = normalizeSkillConfig(raw.skills);
|
|
102
|
+
if (Object.keys(skills).length > 0) merged.skills = { ...(merged.skills ?? {}), ...skills };
|
|
103
|
+
|
|
104
|
+
if (typeof raw.systemPrompt === "string") merged.systemPrompt = raw.systemPrompt;
|
|
105
|
+
if (typeof raw.maxSteps === "number") merged.maxSteps = raw.maxSteps;
|
|
106
|
+
if (typeof raw.printSteps === "boolean") merged.printSteps = raw.printSteps;
|
|
107
|
+
if (typeof raw.fallbackText === "string") merged.fallbackText = raw.fallbackText;
|
|
108
|
+
if (typeof raw.commandWindowLabel === "string") merged.commandWindowLabel = raw.commandWindowLabel;
|
|
109
|
+
if (typeof raw.recursionLimit === "number") merged.recursionLimit = raw.recursionLimit;
|
|
110
|
+
if (typeof raw.memoriesPath === "string") merged.memoriesPath = raw.memoriesPath;
|
|
111
|
+
|
|
112
|
+
return merged;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function hydrateAgentMemoryRuntimeDefaults(
|
|
116
|
+
agents: Record<string, AgentProfileConfig>,
|
|
117
|
+
appRoot: string
|
|
118
|
+
): Promise<Record<string, AgentProfileConfig>> {
|
|
119
|
+
return hydrateNamedScopedDefaults<
|
|
120
|
+
AgentProfileConfig,
|
|
121
|
+
NonNullable<AgentProfileConfig["memory"]>,
|
|
122
|
+
Partial<NonNullable<AgentProfileConfig["memory"]>>
|
|
123
|
+
>(agents, {
|
|
124
|
+
appRoot,
|
|
125
|
+
getScope: (agent) => agent.memory as NonNullable<AgentProfileConfig["memory"]> | undefined,
|
|
126
|
+
setScope: (agent, memory) => ({ ...agent, memory }),
|
|
127
|
+
resolveDefaults: resolveAgentMemoryRuntimeDefaultsFromModule as (ref: string, appRoot: string) => Promise<Partial<NonNullable<AgentProfileConfig["memory"]>>>,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export async function hydrateAgentSkillsRuntimeDefaults(
|
|
132
|
+
agents: Record<string, AgentProfileConfig>,
|
|
133
|
+
appRoot: string
|
|
134
|
+
): Promise<Record<string, AgentProfileConfig>> {
|
|
135
|
+
return hydrateNamedScopedDefaults<
|
|
136
|
+
AgentProfileConfig,
|
|
137
|
+
NonNullable<AgentProfileConfig["skills"]>,
|
|
138
|
+
Partial<NonNullable<AgentProfileConfig["skills"]>>
|
|
139
|
+
>(agents, {
|
|
140
|
+
appRoot,
|
|
141
|
+
getScope: (agent) => agent.skills as NonNullable<AgentProfileConfig["skills"]> | undefined,
|
|
142
|
+
setScope: (agent, skills) => ({ ...agent, skills }),
|
|
143
|
+
resolveDefaults: resolveSkillRuntimeDefaultsFromModule,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function loadDefaultAgentProfiles(): Promise<Record<string, AgentProfileConfig>> {
|
|
148
|
+
if (defaultProfilesPromise) return defaultProfilesPromise;
|
|
149
|
+
defaultProfilesPromise = (async () => {
|
|
150
|
+
const defaultProfileFiles = await discoverDefaultAgentProfileFiles();
|
|
151
|
+
const entries = await Promise.all(
|
|
152
|
+
Object.entries(defaultProfileFiles).map(async ([name, filePath]) => {
|
|
153
|
+
try {
|
|
154
|
+
const raw = await loadModuleConfig<Record<string, unknown>>({
|
|
155
|
+
path: filePath,
|
|
156
|
+
unwrapSpec: true,
|
|
157
|
+
fallback: {},
|
|
158
|
+
});
|
|
159
|
+
return [name, normalizeProfileConfig(raw)] as const;
|
|
160
|
+
} catch {
|
|
161
|
+
return [name, {} as AgentProfileConfig] as const;
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
return Object.fromEntries(entries);
|
|
166
|
+
})();
|
|
167
|
+
return defaultProfilesPromise;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export async function applyDefaultAgentProfiles(
|
|
171
|
+
agents: Record<string, AgentProfileConfig>
|
|
172
|
+
): Promise<Record<string, AgentProfileConfig>> {
|
|
173
|
+
const defaultsMap = await loadDefaultAgentProfiles();
|
|
174
|
+
const out: Record<string, AgentProfileConfig> = { ...agents };
|
|
175
|
+
for (const [name, defaults] of Object.entries(defaultsMap)) {
|
|
176
|
+
out[name] = deepMerge({} as AgentProfileConfig, defaults, out[name] ?? {});
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve as resolvePath } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { asObject, deepMerge, resolveConfigPath, resolveKindResourceFile } from "@easynet/agent-common";
|
|
5
|
+
import { createSkillConfig, resolveSkillRuntimeDefaults } from "@easynet/agent-skill";
|
|
6
|
+
import type {
|
|
7
|
+
ConfigApi,
|
|
8
|
+
AgentProfileConfig,
|
|
9
|
+
AgentRuntimeConfig,
|
|
10
|
+
AgentConfigDefaults,
|
|
11
|
+
SkillConfig,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
import {
|
|
14
|
+
applyDefaultAgentProfiles,
|
|
15
|
+
hydrateAgentMemoryRuntimeDefaults,
|
|
16
|
+
hydrateAgentSkillsRuntimeDefaults,
|
|
17
|
+
normalizeProfileConfig,
|
|
18
|
+
} from "./helpers.js";
|
|
19
|
+
|
|
20
|
+
export type { AgentProfileConfig, AgentRuntimeConfig, AgentConfigDefaults, SkillConfig } from "./types.js";
|
|
21
|
+
|
|
22
|
+
export interface CreateRuntimeConfigOptions {
|
|
23
|
+
configPath?: string;
|
|
24
|
+
overrides?: Partial<AgentRuntimeConfig>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const APP_ROOT = process.cwd();
|
|
28
|
+
const RUNTIME_DIR = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const RUNTIME_PACKAGE_ROOT = resolvePath(RUNTIME_DIR, "../../");
|
|
30
|
+
|
|
31
|
+
type ModuleDefaultConfigPaths = {
|
|
32
|
+
modelsPath?: string;
|
|
33
|
+
memoryPath?: string;
|
|
34
|
+
toolPath?: string;
|
|
35
|
+
skillPath?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function resolveModuleConfigPath(pkgName: string, configRelativePath: string): string | undefined {
|
|
39
|
+
const candidates = [
|
|
40
|
+
resolvePath(RUNTIME_PACKAGE_ROOT, "node_modules", pkgName, configRelativePath),
|
|
41
|
+
resolvePath(APP_ROOT, "node_modules", pkgName, configRelativePath),
|
|
42
|
+
];
|
|
43
|
+
return candidates.find((candidate) => existsSync(candidate));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const MODULE_DEFAULTS: ModuleDefaultConfigPaths = {
|
|
47
|
+
modelsPath: resolveModuleConfigPath("@easynet/agent-model", "config/model.yaml"),
|
|
48
|
+
memoryPath: resolveModuleConfigPath("@easynet/agent-memory", "config/memory.yaml"),
|
|
49
|
+
toolPath: resolveModuleConfigPath("@easynet/agent-tool", "config/tool.yaml"),
|
|
50
|
+
skillPath: resolveModuleConfigPath("@easynet/agent-skill", "config/skill.yaml"),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type SkillsDefaults = Pick<
|
|
54
|
+
NonNullable<AgentProfileConfig["skills"]>,
|
|
55
|
+
"mode" | "inject_metadata" | "embedding_threshold" | "keyword_threshold"
|
|
56
|
+
>;
|
|
57
|
+
|
|
58
|
+
type AppSpec = {
|
|
59
|
+
agents?: {
|
|
60
|
+
list?: Record<string, unknown>;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function toAgentConfigMap(config: AgentRuntimeConfig | undefined): Record<string, AgentProfileConfig> {
|
|
65
|
+
return config?.app?.agent ?? {};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getFirstAgentName(config: AgentRuntimeConfig | undefined): string | undefined {
|
|
69
|
+
return Object.keys(toAgentConfigMap(config))[0];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function pickAgentConfig(
|
|
73
|
+
config: AgentRuntimeConfig | undefined,
|
|
74
|
+
agentName?: string
|
|
75
|
+
): AgentProfileConfig | undefined {
|
|
76
|
+
const map = toAgentConfigMap(config);
|
|
77
|
+
if (agentName && map[agentName]) return map[agentName];
|
|
78
|
+
const firstName = getFirstAgentName(config);
|
|
79
|
+
return firstName ? map[firstName] : undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function requirePath(pathValue: string | undefined, label: string): string {
|
|
83
|
+
if (!pathValue || pathValue.trim().length === 0) {
|
|
84
|
+
throw new Error(`Missing ${label} config path. Set it in agent profile or provide defaults.`);
|
|
85
|
+
}
|
|
86
|
+
return pathValue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function toRuntimeApp(agents: Record<string, AgentProfileConfig>): AgentRuntimeConfig["app"] {
|
|
90
|
+
return {
|
|
91
|
+
agent: agents,
|
|
92
|
+
} as AgentRuntimeConfig["app"];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function loadAgentConfig(configPath?: string): Promise<AgentRuntimeConfig> {
|
|
96
|
+
const appResource = await resolveKindResourceFile<AppSpec>(configPath ?? "config/app.yaml", {
|
|
97
|
+
baseDir: APP_ROOT,
|
|
98
|
+
expectedApiVersion: "easynet.world/v1",
|
|
99
|
+
expectedKind: "AppConfig",
|
|
100
|
+
});
|
|
101
|
+
const spec = asObject(appResource.spec) as AppSpec | undefined;
|
|
102
|
+
const list = spec?.agents?.list ?? {};
|
|
103
|
+
|
|
104
|
+
const mergedAgents = Object.fromEntries(
|
|
105
|
+
Object.entries(list)
|
|
106
|
+
.map(([name, value]) => {
|
|
107
|
+
const entry = asObject(value);
|
|
108
|
+
if (!entry) return null;
|
|
109
|
+
const profileRaw = asObject((entry as { spec?: unknown }).spec) ?? entry;
|
|
110
|
+
const normalized = normalizeProfileConfig(profileRaw);
|
|
111
|
+
return [name, { ...normalized, profile: name } as AgentProfileConfig] as const;
|
|
112
|
+
})
|
|
113
|
+
.filter((item): item is readonly [string, AgentProfileConfig] => item !== null)
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const withDefaults = await applyDefaultAgentProfiles(mergedAgents);
|
|
117
|
+
const memoryHydrated = await hydrateAgentMemoryRuntimeDefaults(withDefaults, APP_ROOT);
|
|
118
|
+
const skillsHydrated = await hydrateAgentSkillsRuntimeDefaults(memoryHydrated, APP_ROOT);
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
app: toRuntimeApp(skillsHydrated),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export async function createRuntimeConfig(options: CreateRuntimeConfigOptions = {}): Promise<AgentRuntimeConfig> {
|
|
126
|
+
const base = await loadAgentConfig(options.configPath);
|
|
127
|
+
if (!options.overrides) return base;
|
|
128
|
+
return deepMerge({} as AgentRuntimeConfig, base, options.overrides);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getModelsConfigPath(
|
|
132
|
+
config?: AgentRuntimeConfig,
|
|
133
|
+
agentName?: string,
|
|
134
|
+
defaults?: AgentConfigDefaults
|
|
135
|
+
): string {
|
|
136
|
+
const agent = pickAgentConfig(config, agentName);
|
|
137
|
+
const p = requirePath(agent?.models?.ref ?? defaults?.modelsPath ?? MODULE_DEFAULTS.modelsPath, "models");
|
|
138
|
+
return resolveConfigPath(p, APP_ROOT);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function getMemoryConfigPath(
|
|
142
|
+
config?: AgentRuntimeConfig,
|
|
143
|
+
agentName?: string,
|
|
144
|
+
defaults?: AgentConfigDefaults
|
|
145
|
+
): string {
|
|
146
|
+
const p = requirePath(
|
|
147
|
+
pickAgentConfig(config, agentName)?.memory?.ref ?? defaults?.memoryPath ?? MODULE_DEFAULTS.memoryPath,
|
|
148
|
+
"memory",
|
|
149
|
+
);
|
|
150
|
+
return resolveConfigPath(p, APP_ROOT);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function getToolConfigPath(
|
|
154
|
+
config: AgentRuntimeConfig | undefined,
|
|
155
|
+
agentName: string | undefined,
|
|
156
|
+
defaults?: AgentConfigDefaults
|
|
157
|
+
): string {
|
|
158
|
+
const name = agentName ?? getFirstAgentName(config);
|
|
159
|
+
const envFromProcess = (process.env.APP_ENV ?? process.env.NODE_ENV ?? "").trim().toLowerCase();
|
|
160
|
+
const env = envFromProcess || "development";
|
|
161
|
+
const isProd = env === "production" || env === "prod";
|
|
162
|
+
const tools = pickAgentConfig(config, name)?.tools;
|
|
163
|
+
|
|
164
|
+
const p = isProd
|
|
165
|
+
? requirePath(
|
|
166
|
+
tools?.production ?? tools?.ref ?? defaults?.toolProdPath ?? defaults?.toolPath ?? MODULE_DEFAULTS.toolPath,
|
|
167
|
+
"tool(production)",
|
|
168
|
+
)
|
|
169
|
+
: requirePath(
|
|
170
|
+
tools?.development ?? tools?.ref ?? defaults?.toolDevPath ?? defaults?.toolPath ?? MODULE_DEFAULTS.toolPath,
|
|
171
|
+
"tool(development)",
|
|
172
|
+
);
|
|
173
|
+
return resolveConfigPath(p, APP_ROOT);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function resolveDefaultAgentName(
|
|
177
|
+
config: AgentRuntimeConfig | undefined,
|
|
178
|
+
preferred?: string
|
|
179
|
+
): string {
|
|
180
|
+
const agents = toAgentConfigMap(config);
|
|
181
|
+
const names = Object.keys(agents);
|
|
182
|
+
if (preferred && agents[preferred]) return preferred;
|
|
183
|
+
const configured = (config?.app as { defaultAgent?: unknown } | undefined)?.defaultAgent;
|
|
184
|
+
if (typeof configured === "string" && agents[configured]) return configured;
|
|
185
|
+
return names[0] ?? preferred ?? "";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function createConfigApi(defaults?: AgentConfigDefaults): ConfigApi<AgentRuntimeConfig> {
|
|
189
|
+
return {
|
|
190
|
+
loadAgentConfig,
|
|
191
|
+
getModelsConfigPath: (config, agentName) => getModelsConfigPath(config, agentName, defaults),
|
|
192
|
+
getMemoryConfigPath: (config, agentName) => getMemoryConfigPath(config, agentName, defaults),
|
|
193
|
+
getToolConfigPath: (config, agentName) => getToolConfigPath(config, agentName, defaults),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export async function getSkillsConfig(
|
|
198
|
+
config: AgentRuntimeConfig | undefined,
|
|
199
|
+
agentName?: string,
|
|
200
|
+
): Promise<SkillConfig | undefined> {
|
|
201
|
+
const raw = pickAgentConfig(config, agentName)?.skills;
|
|
202
|
+
const defaultSkillRef = MODULE_DEFAULTS.skillPath;
|
|
203
|
+
const appLocalSkillsDir = resolvePath(APP_ROOT, "skills");
|
|
204
|
+
const defaultsFromYaml = defaultSkillRef
|
|
205
|
+
? await createSkillConfig({ configPath: resolveConfigPath(defaultSkillRef, APP_ROOT) })
|
|
206
|
+
: null;
|
|
207
|
+
const defaults: Partial<SkillsDefaults> = defaultsFromYaml
|
|
208
|
+
? defaultsFromYaml
|
|
209
|
+
: (defaultSkillRef ? await resolveSkillRuntimeDefaults(defaultSkillRef, APP_ROOT).catch(() => ({})) : {});
|
|
210
|
+
|
|
211
|
+
if (!raw?.ref && existsSync(appLocalSkillsDir)) {
|
|
212
|
+
return {
|
|
213
|
+
path: appLocalSkillsDir,
|
|
214
|
+
mode: raw?.mode ?? defaults.mode,
|
|
215
|
+
inject_metadata: raw?.inject_metadata ?? defaults.inject_metadata,
|
|
216
|
+
embedding_threshold: raw?.embedding_threshold ?? defaults.embedding_threshold,
|
|
217
|
+
keyword_threshold: raw?.keyword_threshold ?? defaults.keyword_threshold,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const skillRef = raw?.ref ?? defaultSkillRef;
|
|
222
|
+
if (!skillRef) return undefined;
|
|
223
|
+
|
|
224
|
+
const resolvedRef = resolveConfigPath(skillRef, APP_ROOT);
|
|
225
|
+
const fromConfig = /\.ya?ml$/i.test(resolvedRef)
|
|
226
|
+
? await createSkillConfig({
|
|
227
|
+
configPath: resolvedRef,
|
|
228
|
+
overrides: {
|
|
229
|
+
mode: raw?.mode,
|
|
230
|
+
inject_metadata: raw?.inject_metadata,
|
|
231
|
+
embedding_threshold: raw?.embedding_threshold,
|
|
232
|
+
keyword_threshold: raw?.keyword_threshold,
|
|
233
|
+
},
|
|
234
|
+
})
|
|
235
|
+
: null;
|
|
236
|
+
if (fromConfig) return fromConfig;
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
path: resolvedRef,
|
|
240
|
+
mode: raw?.mode ?? defaults.mode,
|
|
241
|
+
inject_metadata: raw?.inject_metadata ?? defaults.inject_metadata,
|
|
242
|
+
embedding_threshold: raw?.embedding_threshold ?? defaults.embedding_threshold,
|
|
243
|
+
keyword_threshold: raw?.keyword_threshold ?? defaults.keyword_threshold,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AgentToolConfigRef } from "@easynet/agent-tool";
|
|
2
|
+
import type { SkillConfig, SkillConfigRef } from "@easynet/agent-skill";
|
|
3
|
+
|
|
4
|
+
export type { SkillConfig, SkillConfigRef } from "@easynet/agent-skill";
|
|
5
|
+
export type { AgentToolConfigRef } from "@easynet/agent-tool";
|
|
6
|
+
|
|
7
|
+
export interface AgentMemoryRuntimeRef {
|
|
8
|
+
namespace_mode?: "thread" | "fixed";
|
|
9
|
+
namespace?: string;
|
|
10
|
+
top_k?: number;
|
|
11
|
+
budget_tokens?: number;
|
|
12
|
+
auto_write?: boolean;
|
|
13
|
+
auto_write_scope?: "thread" | "cross_thread" | "knowledge" | "auto";
|
|
14
|
+
auto_write_max_chars?: number;
|
|
15
|
+
auto_write_user?: boolean;
|
|
16
|
+
auto_write_assistant?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type AgentMemoryProfileRef = { ref?: string } & AgentMemoryRuntimeRef;
|
|
20
|
+
|
|
21
|
+
export interface AgentModelConfigRef {
|
|
22
|
+
ref?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type AgentProfileConfig = {
|
|
26
|
+
profile?: string;
|
|
27
|
+
models?: AgentModelConfigRef;
|
|
28
|
+
memory?: AgentMemoryProfileRef;
|
|
29
|
+
tools?: AgentToolConfigRef;
|
|
30
|
+
skills?: SkillConfigRef;
|
|
31
|
+
systemPrompt?: string;
|
|
32
|
+
maxSteps?: number;
|
|
33
|
+
printSteps?: boolean;
|
|
34
|
+
fallbackText?: string;
|
|
35
|
+
commandWindowLabel?: string;
|
|
36
|
+
recursionLimit?: number;
|
|
37
|
+
memoriesPath?: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export interface BaseAgentConfig {
|
|
41
|
+
app?: {
|
|
42
|
+
agent?: Record<string, AgentProfileConfig>;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ConfigApi<TConfig> {
|
|
48
|
+
loadAgentConfig: (configPath?: string) => Promise<TConfig>;
|
|
49
|
+
getModelsConfigPath: (config: TConfig, agentName?: string) => string;
|
|
50
|
+
getMemoryConfigPath: (config: TConfig, agentName?: string) => string;
|
|
51
|
+
getToolConfigPath: (config: TConfig, agentName?: string) => string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface AgentRuntimeConfig extends BaseAgentConfig {}
|
|
55
|
+
|
|
56
|
+
export interface AgentConfigDefaults {
|
|
57
|
+
modelsPath?: string;
|
|
58
|
+
memoryPath?: string;
|
|
59
|
+
toolPath?: string;
|
|
60
|
+
toolDevPath?: string;
|
|
61
|
+
toolProdPath?: string;
|
|
62
|
+
}
|