@easynet/agent-runtime 1.0.3 → 1.0.5

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 (212) hide show
  1. package/.github/workflows/ci.yml +9 -24
  2. package/.github/workflows/release.yml +14 -35
  3. package/agent-runtime/.github/workflows/ci.yml +68 -0
  4. package/agent-runtime/.github/workflows/release.yml +95 -0
  5. package/agent-runtime/.releaserc.cjs +26 -0
  6. package/agent-runtime/config/agent.deep.yaml +25 -0
  7. package/agent-runtime/config/agent.react.yaml +24 -0
  8. package/agent-runtime/example/basic-usage.ts +49 -0
  9. package/agent-runtime/package-lock.json +7740 -0
  10. package/agent-runtime/package.json +49 -0
  11. package/agent-runtime/pnpm-lock.yaml +3712 -0
  12. package/agent-runtime/scripts/resolve-deps.js +54 -0
  13. package/agent-runtime/src/agents/deep-agent.ts +165 -0
  14. package/agent-runtime/src/agents/react-agent.helpers.ts +227 -0
  15. package/agent-runtime/src/agents/react-agent.ts +584 -0
  16. package/{src → agent-runtime/src/agents}/sub-agent.ts +2 -2
  17. package/agent-runtime/src/cli/args.ts +15 -0
  18. package/agent-runtime/src/cli/event-listener.ts +162 -0
  19. package/agent-runtime/src/cli/interactive.ts +144 -0
  20. package/agent-runtime/src/cli/runtime.ts +31 -0
  21. package/agent-runtime/src/cli/spinner.ts +23 -0
  22. package/agent-runtime/src/cli/terminal-render.ts +322 -0
  23. package/agent-runtime/src/cli/types.ts +33 -0
  24. package/agent-runtime/src/cli.ts +134 -0
  25. package/agent-runtime/src/config/helpers.ts +179 -0
  26. package/agent-runtime/src/config/index.ts +245 -0
  27. package/agent-runtime/src/config/types.ts +62 -0
  28. package/agent-runtime/src/core/context.ts +266 -0
  29. package/agent-runtime/src/index.ts +55 -0
  30. package/agent-runtime/tsconfig.json +18 -0
  31. package/apps/imessagebot/README.md +38 -0
  32. package/apps/imessagebot/config/.agent/cache/easynet/agent-tool-buildin/0.0.45/README.md +33 -0
  33. package/apps/imessagebot/config/.agent/cache/easynet/agent-tool-buildin/0.0.45/package-lock.json +15257 -0
  34. package/apps/imessagebot/config/.agent/cache/easynet/agent-tool-buildin/0.0.45/package.json +55 -0
  35. package/apps/imessagebot/config/agents/deep/agent.yaml +31 -0
  36. package/apps/imessagebot/config/agents/react/agent.yaml +58 -0
  37. package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.43/README.md +33 -0
  38. package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.43/package-lock.json +15457 -0
  39. package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.43/package.json +55 -0
  40. package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.46/README.md +33 -0
  41. package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.46/package-lock.json +15257 -0
  42. package/apps/imessagebot/config/agents/shared/.agent/cache/easynet/agent-tool-buildin/0.0.46/package.json +62 -0
  43. package/apps/imessagebot/config/agents/shared/memory.yaml +31 -0
  44. package/apps/imessagebot/config/agents/shared/model.yaml +23 -0
  45. package/apps/imessagebot/config/agents/shared/tool.yaml +13 -0
  46. package/apps/imessagebot/config/app.yaml +14 -0
  47. package/apps/imessagebot/package-lock.json +53695 -0
  48. package/apps/imessagebot/package.json +41 -0
  49. package/apps/imessagebot/pnpm-lock.yaml +1589 -0
  50. package/apps/imessagebot/scripts/resolve-deps.js +41 -0
  51. package/apps/imessagebot/scripts/test-llm.mjs +27 -0
  52. package/apps/imessagebot/scripts/validate-tools-config.mjs +174 -0
  53. package/apps/imessagebot/src/app/config.ts +76 -0
  54. package/apps/imessagebot/src/app/context.ts +39 -0
  55. package/apps/imessagebot/src/config.ts +76 -0
  56. package/apps/imessagebot/src/context.ts +35 -0
  57. package/apps/imessagebot/src/index.ts +17 -0
  58. package/apps/imessagebot/tsconfig.json +18 -0
  59. package/apps/itermbot/.github/workflows/ci.yml +61 -0
  60. package/apps/itermbot/.github/workflows/release.yml +80 -0
  61. package/apps/itermbot/.releaserc.cjs +26 -0
  62. package/apps/itermbot/README.md +82 -0
  63. package/apps/itermbot/config/app.yaml +29 -0
  64. package/apps/itermbot/config/tool.yaml +19 -0
  65. package/apps/itermbot/config/tsconfig.json +18 -0
  66. package/apps/itermbot/macos_disk_usage_agent_plan.md +244 -0
  67. package/apps/itermbot/package-lock.json +53697 -0
  68. package/apps/itermbot/package.json +57 -0
  69. package/apps/itermbot/pnpm-lock.yaml +3966 -0
  70. package/apps/itermbot/scripts/patch-buildin-cache.sh +25 -0
  71. package/apps/itermbot/scripts/resolve-deps.js +41 -0
  72. package/apps/itermbot/scripts/test-llm.mjs +32 -0
  73. package/apps/itermbot/skills/command-explain-and-guard/SKILL.md +39 -0
  74. package/apps/itermbot/skills/command-explain-and-guard/handler.js +86 -0
  75. package/apps/itermbot/skills/disk-usage-investigate/SKILL.md +44 -0
  76. package/apps/itermbot/skills/disk-usage-investigate/handler.js +12 -0
  77. package/apps/itermbot/skills/gpu-ssh-monitor/SKILL.md +64 -0
  78. package/apps/itermbot/skills/repo-triage/SKILL.md +40 -0
  79. package/apps/itermbot/skills/repo-triage/handler.js +56 -0
  80. package/apps/itermbot/skills/test-failure-diagnose/SKILL.md +43 -0
  81. package/apps/itermbot/skills/test-failure-diagnose/handler.js +107 -0
  82. package/apps/itermbot/src/app/config.ts +117 -0
  83. package/apps/itermbot/src/app/context.ts +39 -0
  84. package/apps/itermbot/src/config.ts +95 -0
  85. package/apps/itermbot/src/context.ts +35 -0
  86. package/apps/itermbot/src/index.ts +223 -0
  87. package/apps/itermbot/src/iterm/session-hint.ts +40 -0
  88. package/apps/itermbot/src/iterm/target-panel-policy.ts +220 -0
  89. package/apps/itermbot/src/iterm/target-routing.ts +419 -0
  90. package/apps/itermbot/src/startup/colors.ts +317 -0
  91. package/apps/itermbot/src/startup/diagnostics.ts +97 -0
  92. package/apps/itermbot/src/startup/ui.ts +141 -0
  93. package/apps/itermbot/test/target-panel-policy.test.mjs +60 -0
  94. package/config/agent.deep.yaml +25 -0
  95. package/config/agent.react.yaml +24 -0
  96. package/dist/agents/deep-agent.d.ts +37 -0
  97. package/dist/agents/deep-agent.d.ts.map +1 -0
  98. package/dist/agents/deep-agent.js +115 -0
  99. package/dist/agents/deep-agent.js.map +1 -0
  100. package/dist/agents/react-agent.d.ts +40 -0
  101. package/dist/agents/react-agent.d.ts.map +1 -0
  102. package/dist/agents/react-agent.helpers.d.ts +40 -0
  103. package/dist/agents/react-agent.helpers.d.ts.map +1 -0
  104. package/dist/agents/react-agent.helpers.js +196 -0
  105. package/dist/agents/react-agent.helpers.js.map +1 -0
  106. package/dist/agents/react-agent.js +400 -0
  107. package/dist/agents/react-agent.js.map +1 -0
  108. package/dist/agents/sub-agent.d.ts +34 -0
  109. package/dist/agents/sub-agent.d.ts.map +1 -0
  110. package/dist/agents/sub-agent.js +53 -0
  111. package/dist/agents/sub-agent.js.map +1 -0
  112. package/dist/cli/args.d.ts +8 -0
  113. package/dist/cli/args.d.ts.map +1 -0
  114. package/dist/cli/args.js +9 -0
  115. package/dist/cli/args.js.map +1 -0
  116. package/dist/cli/event-listener.d.ts +3 -0
  117. package/dist/cli/event-listener.d.ts.map +1 -0
  118. package/dist/cli/event-listener.js +131 -0
  119. package/dist/cli/event-listener.js.map +1 -0
  120. package/dist/cli/interactive.d.ts +4 -0
  121. package/dist/cli/interactive.d.ts.map +1 -0
  122. package/dist/cli/interactive.js +118 -0
  123. package/dist/cli/interactive.js.map +1 -0
  124. package/dist/cli/runtime.d.ts +8 -0
  125. package/dist/cli/runtime.d.ts.map +1 -0
  126. package/dist/cli/runtime.js +27 -0
  127. package/dist/cli/runtime.js.map +1 -0
  128. package/dist/cli/spinner.d.ts +2 -0
  129. package/dist/cli/spinner.d.ts.map +1 -0
  130. package/dist/cli/spinner.js +22 -0
  131. package/dist/cli/spinner.js.map +1 -0
  132. package/dist/cli/terminal-render.d.ts +7 -0
  133. package/dist/cli/terminal-render.d.ts.map +1 -0
  134. package/dist/cli/terminal-render.js +282 -0
  135. package/dist/cli/terminal-render.js.map +1 -0
  136. package/dist/cli/types.d.ts +29 -0
  137. package/dist/cli/types.d.ts.map +1 -0
  138. package/dist/cli/types.js +3 -0
  139. package/dist/cli/types.js.map +1 -0
  140. package/dist/cli.d.ts +4 -41
  141. package/dist/cli.d.ts.map +1 -1
  142. package/dist/cli.js +84 -588
  143. package/dist/cli.js.map +1 -1
  144. package/dist/config/helpers.d.ts +6 -0
  145. package/dist/config/helpers.d.ts.map +1 -0
  146. package/dist/config/helpers.js +164 -0
  147. package/dist/config/helpers.js.map +1 -0
  148. package/dist/config/index.d.ts +15 -0
  149. package/dist/config/index.d.ts.map +1 -0
  150. package/dist/config/index.js +160 -0
  151. package/dist/config/index.js.map +1 -0
  152. package/dist/config/types.d.ts +57 -0
  153. package/dist/config/types.d.ts.map +1 -0
  154. package/dist/config/types.js +2 -0
  155. package/dist/config/types.js.map +1 -0
  156. package/dist/context.d.ts +8 -69
  157. package/dist/context.d.ts.map +1 -1
  158. package/dist/context.js +44 -24
  159. package/dist/context.js.map +1 -1
  160. package/dist/core/context.d.ts +66 -0
  161. package/dist/core/context.d.ts.map +1 -0
  162. package/dist/core/context.js +149 -0
  163. package/dist/core/context.js.map +1 -0
  164. package/dist/deep-agent.d.ts +5 -2
  165. package/dist/deep-agent.d.ts.map +1 -1
  166. package/dist/deep-agent.js +44 -11
  167. package/dist/deep-agent.js.map +1 -1
  168. package/dist/index.d.ts +6 -6
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.js +6 -6
  171. package/dist/index.js.map +1 -1
  172. package/dist/middleware/malformed-tool-call-middleware.d.ts +8 -0
  173. package/dist/middleware/malformed-tool-call-middleware.d.ts.map +1 -0
  174. package/dist/middleware/malformed-tool-call-middleware.js +191 -0
  175. package/dist/middleware/malformed-tool-call-middleware.js.map +1 -0
  176. package/dist/react-agent.d.ts +2 -2
  177. package/dist/react-agent.d.ts.map +1 -1
  178. package/dist/react-agent.js +28 -9
  179. package/dist/react-agent.js.map +1 -1
  180. package/package.json +1 -1
  181. package/scripts/resolve-deps.js +54 -0
  182. package/src/agents/deep-agent.ts +165 -0
  183. package/src/agents/react-agent.helpers.ts +227 -0
  184. package/src/agents/react-agent.ts +584 -0
  185. package/src/agents/sub-agent.ts +82 -0
  186. package/src/cli/args.ts +15 -0
  187. package/src/cli/event-listener.ts +162 -0
  188. package/src/cli/interactive.ts +144 -0
  189. package/src/cli/runtime.ts +31 -0
  190. package/src/cli/spinner.ts +23 -0
  191. package/src/cli/terminal-render.ts +322 -0
  192. package/src/cli/types.ts +33 -0
  193. package/src/cli.ts +91 -702
  194. package/src/config/helpers.ts +179 -0
  195. package/src/config/index.ts +245 -0
  196. package/src/config/types.ts +62 -0
  197. package/src/core/context.ts +266 -0
  198. package/src/index.ts +13 -11
  199. package/src/middleware/malformed-tool-call-middleware.ts +239 -0
  200. package/src/types/markdown-it-terminal.d.ts +4 -0
  201. package/src/types/marked-terminal.d.ts +16 -0
  202. package/dist/config.d.ts +0 -86
  203. package/dist/config.d.ts.map +0 -1
  204. package/dist/config.js +0 -84
  205. package/dist/config.js.map +0 -1
  206. package/src/config.ts +0 -177
  207. package/src/context.ts +0 -247
  208. package/src/deep-agent.ts +0 -104
  209. package/src/react-agent.ts +0 -576
  210. /package/{src → agent-runtime/src/middleware}/malformed-tool-call-middleware.ts +0 -0
  211. /package/{src → agent-runtime/src/types}/markdown-it-terminal.d.ts +0 -0
  212. /package/{src → agent-runtime/src/types}/marked-terminal.d.ts +0 -0
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * resolve-deps.js
4
+ *
5
+ * Run automatically via `preinstall` npm hook.
6
+ * In CI (CI=true), rewrites file: references in package.json to npm versions
7
+ * so that `npm install` can resolve them without local sibling directories.
8
+ *
9
+ * Local development: no-op (CI env var is not set).
10
+ */
11
+
12
+ import { readFileSync, writeFileSync } from 'fs';
13
+ import { resolve, dirname } from 'path';
14
+ import { fileURLToPath } from 'url';
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const pkgPath = resolve(__dirname, '..', 'package.json');
18
+
19
+ if (!process.env.CI) {
20
+ process.exit(0);
21
+ }
22
+
23
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
24
+ let changed = false;
25
+
26
+ for (const section of ['dependencies', 'devDependencies']) {
27
+ const deps = pkg[section];
28
+ if (!deps) continue;
29
+ for (const [name, version] of Object.entries(deps)) {
30
+ if (name.startsWith('@easynet/') && typeof version === 'string' && version.startsWith('file:')) {
31
+ deps[name] = 'latest';
32
+ changed = true;
33
+ console.log(`[resolve-deps] ${name}: file: → latest`);
34
+ }
35
+ }
36
+ }
37
+
38
+ if (changed) {
39
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
40
+ console.log('[resolve-deps] package.json updated for CI.');
41
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Quick LLM config test. Run from app root: npm run test:llm
3
+ */
4
+ import { createAgentLlm } from "@easynet/agent-model";
5
+
6
+ async function main() {
7
+ try {
8
+ console.log("[test-llm] Loading LLM from config/agents/shared/model.yaml ...");
9
+ const llm = await createAgentLlm({
10
+ configPath: "config/agents/shared/model.yaml",
11
+ checkConnectivity: false,
12
+ });
13
+
14
+ console.log("[test-llm] Invoking LLM ...");
15
+ const res = await llm.invoke(
16
+ "In one sentence, introduce yourself and say you are being used to test iMessageBot's LLM config."
17
+ );
18
+
19
+ console.log("[test-llm] Raw response:");
20
+ console.log(JSON.stringify(res, null, 2));
21
+ } catch (err) {
22
+ console.error("[test-llm] Error:", err);
23
+ process.exit(1);
24
+ }
25
+ }
26
+
27
+ main();
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ import { resolve, dirname } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { existsSync } from "node:fs";
5
+ import { loadYamlFile } from "@easynet/agent-common";
6
+ import { createLangChainAgentTools } from "@easynet/agent-tool/api";
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const APP_ROOT = resolve(__dirname, "..");
11
+ const CONFIG_DIR = resolve(APP_ROOT, "config");
12
+
13
+ function fail(message) {
14
+ console.error(`[validate-tools-config] ${message}`);
15
+ process.exit(1);
16
+ }
17
+
18
+ function assert(condition, message) {
19
+ if (!condition) fail(message);
20
+ }
21
+
22
+ function asArray(value) {
23
+ return Array.isArray(value) ? value : [];
24
+ }
25
+
26
+ function normalizePath(p, baseDir = APP_ROOT) {
27
+ return p.startsWith("/") ? p : resolve(baseDir, p);
28
+ }
29
+
30
+ async function loadYaml(path) {
31
+ const v = await loadYamlFile(path);
32
+ return v ?? {};
33
+ }
34
+
35
+ function getCoreToolsOptions() {
36
+ return {
37
+ sandboxRoot: APP_ROOT,
38
+ allowedHosts: ["api.github.com", "duckduckgo.com", "www.duckduckgo.com"],
39
+ };
40
+ }
41
+
42
+ function resolveToolConfigPaths(reactAgentConfig, reactAgentDir) {
43
+ return {
44
+ toolsDefaultPath: normalizePath(reactAgentConfig?.spec?.tools?.ref ?? "../shared/tool.yaml", reactAgentDir),
45
+ toolsDevPath: normalizePath(reactAgentConfig?.spec?.tools?.development ?? "../shared/tool.development.yaml", reactAgentDir),
46
+ toolsProdPath: normalizePath(reactAgentConfig?.spec?.tools?.production ?? "../shared/tool.production.yaml", reactAgentDir),
47
+ };
48
+ }
49
+
50
+ function extractToolsConfigSummary(config) {
51
+ const spec = config?.spec ?? {};
52
+ const toolsNode = spec?.tools ?? {};
53
+ return {
54
+ tools: asArray(toolsNode?.list ?? toolsNode),
55
+ sandboxedPath: toolsNode?.sandboxedPath ?? spec?.sandboxedPath,
56
+ };
57
+ }
58
+
59
+ function validateDefaultConfig(defaultConfig) {
60
+ const summary = extractToolsConfigSummary(defaultConfig);
61
+ assert(typeof summary.sandboxedPath === "string", "tool.yaml missing sandboxedPath");
62
+ assert(summary.tools.length > 0, "tool.yaml tools must not be empty");
63
+ assert(
64
+ summary.tools.some(
65
+ (t) =>
66
+ typeof t === "string" &&
67
+ (t.startsWith("file:") || t.startsWith("npm:@easynet/agent-tool-buildin")),
68
+ ),
69
+ "tool.yaml should use file:... or npm:@easynet/agent-tool-buildin",
70
+ );
71
+ return summary;
72
+ }
73
+
74
+ function validateVariantConfig(args) {
75
+ const { config, label, expectedSandboxedPath, defaultLoadedToolsLength, configFilePath } = args;
76
+ const summary = extractToolsConfigSummary(config);
77
+ assert(typeof summary.sandboxedPath === "string", `${label} missing sandboxedPath`);
78
+ assert(summary.sandboxedPath === expectedSandboxedPath, `${label} sandboxedPath should match tool.yaml`);
79
+ assert(summary.tools.length > 0, `${label} tools must not be empty`);
80
+ const loadedTools = createLangChainAgentTools({ configFilePath, coreTools: getCoreToolsOptions() });
81
+ assert(
82
+ loadedTools.length === defaultLoadedToolsLength,
83
+ `${label} count mismatch: default=${defaultLoadedToolsLength}, current=${loadedTools.length}`,
84
+ );
85
+ }
86
+
87
+ function assertRequiredToolsLoaded(defaultLoadedTools) {
88
+ const names = new Set(defaultLoadedTools.map((t) => t.name));
89
+ const hasTool = (shortName) =>
90
+ Array.from(names).some((fullName) => fullName === shortName || fullName.endsWith(`.${shortName}`));
91
+ const required = [
92
+ "platformGetCapabilities",
93
+ "messagesListChats",
94
+ "messagesReadChat",
95
+ "messagesSendByHandle",
96
+ "notesList",
97
+ "notesRead",
98
+ "notesCreate",
99
+ "remindersList",
100
+ "remindersCreate",
101
+ "calendarListEvents",
102
+ "calendarCreateEvent",
103
+ "safariGetActiveTab",
104
+ "safariReadPageContent",
105
+ "cronListEntries",
106
+ "cronSetTaggedEntry",
107
+ "gitStatus",
108
+ "ghRead",
109
+ ];
110
+ for (const name of required) {
111
+ assert(hasTool(name), `required tool not loaded: ${name}`);
112
+ }
113
+ }
114
+
115
+ async function main() {
116
+ const appYamlPath = resolve(CONFIG_DIR, "app.yaml");
117
+ assert(existsSync(appYamlPath), `missing config file: ${appYamlPath}`);
118
+
119
+ const appConfig = await loadYaml(appYamlPath);
120
+ const appConfigDir = dirname(appYamlPath);
121
+ const reactAgentRef = appConfig?.spec?.agents?.list?.react?.ref;
122
+ const reactAgentYamlPath = normalizePath(reactAgentRef ?? "./agents/react/agent.yaml", appConfigDir);
123
+ assert(existsSync(reactAgentYamlPath), `react agent config not found: ${reactAgentYamlPath}`);
124
+ const reactAgentConfig = await loadYaml(reactAgentYamlPath);
125
+ const reactAgentDir = dirname(reactAgentYamlPath);
126
+
127
+ const { toolsDefaultPath, toolsDevPath, toolsProdPath } = resolveToolConfigPaths(reactAgentConfig, reactAgentDir);
128
+
129
+ assert(existsSync(toolsDefaultPath), `tool config not found: ${toolsDefaultPath}`);
130
+
131
+ const defaultConfig = await loadYaml(toolsDefaultPath);
132
+ const hasDevFile = existsSync(toolsDevPath);
133
+ const hasProdFile = existsSync(toolsProdPath);
134
+ const devConfig = hasDevFile ? await loadYaml(toolsDevPath) : null;
135
+ const prodConfig = hasProdFile ? await loadYaml(toolsProdPath) : null;
136
+
137
+ const { sandboxedPath: defaultSandboxedPath } = validateDefaultConfig(defaultConfig);
138
+ const defaultLoadedTools = createLangChainAgentTools({
139
+ configFilePath: toolsDefaultPath,
140
+ coreTools: getCoreToolsOptions(),
141
+ });
142
+
143
+ assert(defaultLoadedTools.length > 0, "tool.yaml loads 0 tools");
144
+
145
+ if (devConfig) {
146
+ validateVariantConfig({
147
+ config: devConfig,
148
+ label: "tool.development.yaml",
149
+ expectedSandboxedPath: defaultSandboxedPath,
150
+ defaultLoadedToolsLength: defaultLoadedTools.length,
151
+ configFilePath: toolsDevPath,
152
+ });
153
+ }
154
+
155
+ if (prodConfig) {
156
+ validateVariantConfig({
157
+ config: prodConfig,
158
+ label: "tool.production.yaml",
159
+ expectedSandboxedPath: defaultSandboxedPath,
160
+ defaultLoadedToolsLength: defaultLoadedTools.length,
161
+ configFilePath: toolsProdPath,
162
+ });
163
+ }
164
+
165
+ assertRequiredToolsLoaded(defaultLoadedTools);
166
+
167
+ console.log(
168
+ `[validate-tools-config] OK: default=${defaultLoadedTools.length}, devFile=${hasDevFile}, prodFile=${hasProdFile}`,
169
+ );
170
+ }
171
+
172
+ main().catch((error) => {
173
+ fail(error instanceof Error ? error.message : String(error));
174
+ });
@@ -0,0 +1,76 @@
1
+ import { asObject, resolveKindResourceFile } from "@easynet/agent-common";
2
+ import {
3
+ createRuntimeConfig,
4
+ getModelsConfigPath as getRuntimeModelsConfigPath,
5
+ getMemoryConfigPath as getRuntimeMemoryConfigPath,
6
+ getToolConfigPath as getRuntimeToolConfigPath,
7
+ resolveDefaultAgentName as resolveRuntimeDefaultAgentName,
8
+ type AgentProfileConfig,
9
+ } from "@easynet/agent-runtime";
10
+
11
+ type IMessageAppSpec = {
12
+ agent?: string;
13
+ };
14
+
15
+ export interface AppConfig {
16
+ app?: {
17
+ agent?: Record<string, AgentProfileConfig>;
18
+ defaultAgent?: string;
19
+ };
20
+ }
21
+
22
+ export interface AppConfigDefaults {
23
+ modelsPath?: string;
24
+ memoryPath?: string;
25
+ toolPath?: string;
26
+ toolDevPath?: string;
27
+ toolProdPath?: string;
28
+ }
29
+
30
+ export async function loadAppConfig(configPath?: string): Promise<AppConfig> {
31
+ const appResource = await resolveKindResourceFile<IMessageAppSpec>(configPath ?? "config/app.yaml", {
32
+ baseDir: process.cwd(),
33
+ expectedApiVersion: "easynet.world/v1",
34
+ expectedKind: "AppConfig",
35
+ });
36
+ const spec = asObject(appResource.spec) as IMessageAppSpec | undefined;
37
+ const runtimeConfig = await createRuntimeConfig({
38
+ configPath,
39
+ overrides: {
40
+ app: {
41
+ defaultAgent: spec?.agent,
42
+ },
43
+ },
44
+ });
45
+ const defaultAgent = resolveRuntimeDefaultAgentName(runtimeConfig, spec?.agent);
46
+ return {
47
+ app: {
48
+ agent: runtimeConfig.app?.agent,
49
+ defaultAgent,
50
+ },
51
+ };
52
+ }
53
+
54
+ export function getModelsConfigPath(
55
+ config: AppConfig,
56
+ agentName?: string,
57
+ defaults?: AppConfigDefaults,
58
+ ): string {
59
+ return getRuntimeModelsConfigPath(config, agentName, defaults);
60
+ }
61
+
62
+ export function getMemoryConfigPath(
63
+ config: AppConfig,
64
+ agentName?: string,
65
+ defaults?: AppConfigDefaults,
66
+ ): string {
67
+ return getRuntimeMemoryConfigPath(config, agentName, defaults);
68
+ }
69
+
70
+ export function getToolConfigPath(
71
+ config: AppConfig,
72
+ agentName?: string,
73
+ defaults?: AppConfigDefaults,
74
+ ): string {
75
+ return getRuntimeToolConfigPath(config, agentName, defaults);
76
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared runtime context: LLM, memory, tools.
3
+ * Built once and passed to both ReAct and Deep agents.
4
+ */
5
+ import {
6
+ createContextBuilders,
7
+ type AppContextBuilders,
8
+ type BotContext,
9
+ type BotTool,
10
+ type CreateContextOptions,
11
+ } from "@easynet/agent-runtime";
12
+ import {
13
+ loadAppConfig,
14
+ getModelsConfigPath,
15
+ getMemoryConfigPath,
16
+ getToolConfigPath,
17
+ type AppConfig,
18
+ } from "./config.js";
19
+
20
+ export type { BotContext, BotTool, CreateContextOptions };
21
+
22
+ const builders: AppContextBuilders = createContextBuilders<AppConfig>({
23
+ configApi: {
24
+ loadAgentConfig: loadAppConfig,
25
+ getModelsConfigPath: (config: AppConfig, agentName?: string) => getModelsConfigPath(config, agentName),
26
+ getMemoryConfigPath: (config: AppConfig, agentName?: string) => getMemoryConfigPath(config, agentName),
27
+ getToolConfigPath: (config: AppConfig, agentName?: string) => getToolConfigPath(config, agentName),
28
+ },
29
+ });
30
+
31
+ export const getAgentLlm: AppContextBuilders["createAgentLlm"] = builders.createAgentLlm;
32
+ export const getAgentMemory: AppContextBuilders["createAgentMemory"] = builders.createAgentMemory;
33
+ export const getAgentTools: AppContextBuilders["createAgentTools"] = builders.createAgentTools;
34
+
35
+ export const createAgentLlm: AppContextBuilders["createAgentLlm"] = builders.createAgentLlm;
36
+ export const createAgentMemory: AppContextBuilders["createAgentMemory"] = builders.createAgentMemory;
37
+ export const createAgentTools: AppContextBuilders["createAgentTools"] = builders.createAgentTools;
38
+ export const createAgent: AppContextBuilders["createAgent"] = builders.createAgent;
39
+ export const createBotContext: AppContextBuilders["createBotContext"] = builders.createBotContext;
@@ -0,0 +1,76 @@
1
+ import { asObject, resolveKindResourceFile } from "@easynet/agent-common";
2
+ import {
3
+ createRuntimeConfig,
4
+ getModelsConfigPath as getRuntimeModelsConfigPath,
5
+ getMemoryConfigPath as getRuntimeMemoryConfigPath,
6
+ getToolConfigPath as getRuntimeToolConfigPath,
7
+ resolveDefaultAgentName as resolveRuntimeDefaultAgentName,
8
+ type AgentProfileConfig,
9
+ } from "@easynet/agent-runtime";
10
+
11
+ type IMessageAppSpec = {
12
+ agent?: string;
13
+ };
14
+
15
+ export interface AppConfig {
16
+ app?: {
17
+ agent?: Record<string, AgentProfileConfig>;
18
+ defaultAgent?: string;
19
+ };
20
+ }
21
+
22
+ export interface AppConfigDefaults {
23
+ modelsPath?: string;
24
+ memoryPath?: string;
25
+ toolPath?: string;
26
+ toolDevPath?: string;
27
+ toolProdPath?: string;
28
+ }
29
+
30
+ export async function loadAppConfig(configPath?: string): Promise<AppConfig> {
31
+ const appResource = await resolveKindResourceFile<IMessageAppSpec>(configPath ?? "config/app.yaml", {
32
+ baseDir: process.cwd(),
33
+ expectedApiVersion: "easynet.world/v1",
34
+ expectedKind: "AppConfig",
35
+ });
36
+ const spec = asObject(appResource.spec) as IMessageAppSpec | undefined;
37
+ const runtimeConfig = await createRuntimeConfig({
38
+ configPath,
39
+ overrides: {
40
+ app: {
41
+ defaultAgent: spec?.agent,
42
+ },
43
+ },
44
+ });
45
+ const defaultAgent = resolveRuntimeDefaultAgentName(runtimeConfig, spec?.agent);
46
+ return {
47
+ app: {
48
+ agent: runtimeConfig.app?.agent,
49
+ defaultAgent,
50
+ },
51
+ };
52
+ }
53
+
54
+ export function getModelsConfigPath(
55
+ config: AppConfig,
56
+ agentName?: string,
57
+ defaults?: AppConfigDefaults,
58
+ ): string {
59
+ return getRuntimeModelsConfigPath(config, agentName, defaults);
60
+ }
61
+
62
+ export function getMemoryConfigPath(
63
+ config: AppConfig,
64
+ agentName?: string,
65
+ defaults?: AppConfigDefaults,
66
+ ): string {
67
+ return getRuntimeMemoryConfigPath(config, agentName, defaults);
68
+ }
69
+
70
+ export function getToolConfigPath(
71
+ config: AppConfig,
72
+ agentName?: string,
73
+ defaults?: AppConfigDefaults,
74
+ ): string {
75
+ return getRuntimeToolConfigPath(config, agentName, defaults);
76
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Shared runtime context: LLM, memory, tools.
3
+ * Built once and passed to both ReAct and Deep agents.
4
+ */
5
+ import {
6
+ createContextBuilders,
7
+ type AppContextBuilders,
8
+ type BotContext,
9
+ type BotTool,
10
+ type CreateContextOptions,
11
+ } from "@easynet/agent-runtime";
12
+ import {
13
+ loadAppConfig,
14
+ getModelsConfigPath,
15
+ getMemoryConfigPath,
16
+ getToolConfigPath,
17
+ type AppConfig,
18
+ } from "./config.js";
19
+
20
+ export type { BotContext, BotTool, CreateContextOptions };
21
+
22
+ const builders: AppContextBuilders = createContextBuilders<AppConfig>({
23
+ configApi: {
24
+ loadAgentConfig: loadAppConfig,
25
+ getModelsConfigPath: (config: AppConfig, agentName?: string) => getModelsConfigPath(config, agentName),
26
+ getMemoryConfigPath: (config: AppConfig, agentName?: string) => getMemoryConfigPath(config, agentName),
27
+ getToolConfigPath: (config: AppConfig, agentName?: string) => getToolConfigPath(config, agentName),
28
+ },
29
+ });
30
+
31
+ export const createAgentLlm: AppContextBuilders["createAgentLlm"] = builders.createAgentLlm;
32
+ export const createAgentMemory: AppContextBuilders["createAgentMemory"] = builders.createAgentMemory;
33
+ export const createAgentTools: AppContextBuilders["createAgentTools"] = builders.createAgentTools;
34
+ export const createAgent: AppContextBuilders["createAgent"] = builders.createAgent;
35
+ export const createBotContext: AppContextBuilders["createBotContext"] = builders.createBotContext;
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * iMessageBot: ReAct agent (LangChain) + Deep agent (DeepAgents).
4
+ * Usage:
5
+ * npm start # interactive: choose agent then chat
6
+ * npm run react # use ReAct agent
7
+ * npm run deep # use Deep agent
8
+ * node dist/index.js react "Your question"
9
+ * node dist/index.js deep "Your question"
10
+ */
11
+ import { runAppCli } from "@easynet/agent-runtime";
12
+ import { createBotContext } from "./context.js";
13
+
14
+ runAppCli({
15
+ appName: "iMessageBot",
16
+ createBotContext,
17
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "declaration": true,
12
+ "declarationMap": true,
13
+ "sourceMap": true,
14
+ "resolveJsonModule": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }
@@ -0,0 +1,61 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ['**']
6
+ pull_request:
7
+ branches: ['**']
8
+ repository_dispatch:
9
+ types:
10
+ - easynet-package-updated
11
+
12
+ concurrency:
13
+ group: ${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ test:
18
+ name: Test & Build
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 25
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Setup Node.js
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: '20'
29
+ cache: 'npm'
30
+ registry-url: 'https://registry.npmjs.org'
31
+
32
+ - name: Force npm registry to npmjs.org
33
+ run: |
34
+ touch .npmrc
35
+ grep -q '^registry=https://registry.npmjs.org' .npmrc || echo "registry=https://registry.npmjs.org/" >> .npmrc
36
+ grep -q '@easynet:registry=' .npmrc || echo "@easynet:registry=https://registry.npmjs.org/" >> .npmrc
37
+ grep -q '@wallee:registry=' .npmrc || echo "@wallee:registry=https://registry.npmjs.org/" >> .npmrc
38
+
39
+ - name: Install dependencies
40
+ env:
41
+ NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/"
42
+ run: npm install --legacy-peer-deps
43
+
44
+ - name: Build
45
+ run: npm run build --if-present
46
+
47
+ - name: Typecheck
48
+ run: npm run typecheck --if-present
49
+
50
+ - name: Test
51
+ run: npm test --if-present
52
+
53
+ - name: Diagnostics (on failure)
54
+ if: failure()
55
+ run: |
56
+ echo "Node: $(node -v) | npm: $(npm -v)"
57
+ echo "--- .npmrc ---"
58
+ cat .npmrc 2>&1 || true
59
+ echo "--- npm config ---"
60
+ npm config list 2>&1 || true
61
+ npm ls --depth=0 2>&1 | head -50
@@ -0,0 +1,80 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ workflow_dispatch:
8
+ repository_dispatch:
9
+ types:
10
+ - easynet-package-updated
11
+
12
+ concurrency:
13
+ group: ${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ permissions:
17
+ contents: write
18
+
19
+ jobs:
20
+ release:
21
+ name: Release
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 30
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v4
27
+ with:
28
+ fetch-depth: 0
29
+ token: ${{ secrets.GITHUB_TOKEN }}
30
+
31
+ - name: Setup Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version: '20'
35
+ cache: 'npm'
36
+ registry-url: 'https://registry.npmjs.org'
37
+
38
+ - name: Force npm registry to npmjs.org
39
+ run: |
40
+ touch .npmrc
41
+ grep -q '^registry=https://registry.npmjs.org' .npmrc || echo "registry=https://registry.npmjs.org/" >> .npmrc
42
+ grep -q '@easynet:registry=' .npmrc || echo "@easynet:registry=https://registry.npmjs.org/" >> .npmrc
43
+ grep -q '@wallee:registry=' .npmrc || echo "@wallee:registry=https://registry.npmjs.org/" >> .npmrc
44
+
45
+ - name: Use @easynet deps from npm (CI has no file:../../)
46
+ run: |
47
+ node -e "
48
+ const fs = require('fs');
49
+ const pkgPath = 'package.json';
50
+ const p = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
51
+ const deps = { ...p.dependencies, ...p.devDependencies };
52
+ let changed = false;
53
+ for (const [name, v] of Object.entries(deps)) {
54
+ if (name.startsWith('@easynet/') && typeof v === 'string' && v.startsWith('file:')) {
55
+ if (p.dependencies[name]) { p.dependencies[name] = 'latest'; changed = true; }
56
+ if (p.devDependencies[name]) { p.devDependencies[name] = 'latest'; changed = true; }
57
+ }
58
+ }
59
+ if (changed) fs.writeFileSync(pkgPath, JSON.stringify(p, null, 2) + '\n');
60
+ "
61
+
62
+ - name: Install dependencies
63
+ env:
64
+ NPM_CONFIG_REGISTRY: "https://registry.npmjs.org/"
65
+ run: npm install --legacy-peer-deps
66
+
67
+ - name: Build
68
+ run: npm run build --if-present
69
+
70
+ - name: Typecheck
71
+ run: npm run typecheck --if-present
72
+
73
+ - name: Test
74
+ run: npm test --if-present
75
+
76
+ - name: Release
77
+ env:
78
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
80
+ run: npx semantic-release
@@ -0,0 +1,26 @@
1
+ /** @type {import('semantic-release').GlobalConfig} */
2
+ module.exports = {
3
+ branches: ['master'],
4
+ plugins: [
5
+ [
6
+ '@semantic-release/commit-analyzer',
7
+ {
8
+ releaseRules: [
9
+ { type: 'feat', release: 'patch' },
10
+ { type: 'fix', release: 'patch' },
11
+ { type: 'docs', release: 'patch' },
12
+ { type: 'chore', release: 'patch' },
13
+ { type: 'refactor', release: 'patch' },
14
+ { type: 'perf', release: 'patch' },
15
+ { type: 'test', release: 'patch' },
16
+ { type: 'ci', release: 'patch' },
17
+ { type: 'build', release: 'patch' },
18
+ { message: '*', release: 'patch' },
19
+ ],
20
+ },
21
+ ],
22
+ '@semantic-release/release-notes-generator',
23
+ '@semantic-release/npm',
24
+ '@semantic-release/git',
25
+ ],
26
+ };