@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.
Files changed (205) 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 +69 -0
  4. package/agent-runtime/.github/workflows/release.yml +118 -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/config.ts +76 -0
  54. package/apps/imessagebot/src/context.ts +35 -0
  55. package/apps/imessagebot/src/index.ts +17 -0
  56. package/apps/imessagebot/tsconfig.json +18 -0
  57. package/apps/itermbot/.github/workflows/ci.yml +61 -0
  58. package/apps/itermbot/.github/workflows/release.yml +80 -0
  59. package/apps/itermbot/.releaserc.cjs +26 -0
  60. package/apps/itermbot/README.md +82 -0
  61. package/apps/itermbot/config/app.yaml +29 -0
  62. package/apps/itermbot/config/tsconfig.json +18 -0
  63. package/apps/itermbot/macos_disk_usage_agent_plan.md +244 -0
  64. package/apps/itermbot/package-lock.json +53697 -0
  65. package/apps/itermbot/package.json +57 -0
  66. package/apps/itermbot/pnpm-lock.yaml +3966 -0
  67. package/apps/itermbot/scripts/patch-buildin-cache.sh +25 -0
  68. package/apps/itermbot/scripts/resolve-deps.js +41 -0
  69. package/apps/itermbot/scripts/test-llm.mjs +32 -0
  70. package/apps/itermbot/skills/command-explain-and-guard/SKILL.md +39 -0
  71. package/apps/itermbot/skills/command-explain-and-guard/handler.js +86 -0
  72. package/apps/itermbot/skills/disk-usage-investigate/SKILL.md +44 -0
  73. package/apps/itermbot/skills/disk-usage-investigate/handler.js +12 -0
  74. package/apps/itermbot/skills/gpu-ssh-monitor/SKILL.md +64 -0
  75. package/apps/itermbot/skills/repo-triage/SKILL.md +40 -0
  76. package/apps/itermbot/skills/repo-triage/handler.js +56 -0
  77. package/apps/itermbot/skills/test-failure-diagnose/SKILL.md +43 -0
  78. package/apps/itermbot/skills/test-failure-diagnose/handler.js +107 -0
  79. package/apps/itermbot/src/config.ts +95 -0
  80. package/apps/itermbot/src/context.ts +35 -0
  81. package/apps/itermbot/src/index.ts +223 -0
  82. package/apps/itermbot/src/iterm/session-hint.ts +40 -0
  83. package/apps/itermbot/src/iterm/target-routing.ts +419 -0
  84. package/apps/itermbot/src/startup/colors.ts +317 -0
  85. package/apps/itermbot/src/startup/diagnostics.ts +97 -0
  86. package/apps/itermbot/src/startup/ui.ts +141 -0
  87. package/config/agent.deep.yaml +25 -0
  88. package/config/agent.react.yaml +24 -0
  89. package/dist/agents/deep-agent.d.ts +37 -0
  90. package/dist/agents/deep-agent.d.ts.map +1 -0
  91. package/dist/agents/deep-agent.js +115 -0
  92. package/dist/agents/deep-agent.js.map +1 -0
  93. package/dist/agents/react-agent.d.ts +40 -0
  94. package/dist/agents/react-agent.d.ts.map +1 -0
  95. package/dist/agents/react-agent.helpers.d.ts +40 -0
  96. package/dist/agents/react-agent.helpers.d.ts.map +1 -0
  97. package/dist/agents/react-agent.helpers.js +196 -0
  98. package/dist/agents/react-agent.helpers.js.map +1 -0
  99. package/dist/agents/react-agent.js +400 -0
  100. package/dist/agents/react-agent.js.map +1 -0
  101. package/dist/agents/sub-agent.d.ts +34 -0
  102. package/dist/agents/sub-agent.d.ts.map +1 -0
  103. package/dist/agents/sub-agent.js +53 -0
  104. package/dist/agents/sub-agent.js.map +1 -0
  105. package/dist/cli/args.d.ts +8 -0
  106. package/dist/cli/args.d.ts.map +1 -0
  107. package/dist/cli/args.js +9 -0
  108. package/dist/cli/args.js.map +1 -0
  109. package/dist/cli/event-listener.d.ts +3 -0
  110. package/dist/cli/event-listener.d.ts.map +1 -0
  111. package/dist/cli/event-listener.js +131 -0
  112. package/dist/cli/event-listener.js.map +1 -0
  113. package/dist/cli/interactive.d.ts +4 -0
  114. package/dist/cli/interactive.d.ts.map +1 -0
  115. package/dist/cli/interactive.js +118 -0
  116. package/dist/cli/interactive.js.map +1 -0
  117. package/dist/cli/runtime.d.ts +8 -0
  118. package/dist/cli/runtime.d.ts.map +1 -0
  119. package/dist/cli/runtime.js +27 -0
  120. package/dist/cli/runtime.js.map +1 -0
  121. package/dist/cli/spinner.d.ts +2 -0
  122. package/dist/cli/spinner.d.ts.map +1 -0
  123. package/dist/cli/spinner.js +22 -0
  124. package/dist/cli/spinner.js.map +1 -0
  125. package/dist/cli/terminal-render.d.ts +7 -0
  126. package/dist/cli/terminal-render.d.ts.map +1 -0
  127. package/dist/cli/terminal-render.js +282 -0
  128. package/dist/cli/terminal-render.js.map +1 -0
  129. package/dist/cli/types.d.ts +29 -0
  130. package/dist/cli/types.d.ts.map +1 -0
  131. package/dist/cli/types.js +3 -0
  132. package/dist/cli/types.js.map +1 -0
  133. package/dist/cli.d.ts +4 -41
  134. package/dist/cli.d.ts.map +1 -1
  135. package/dist/cli.js +84 -588
  136. package/dist/cli.js.map +1 -1
  137. package/dist/config/helpers.d.ts +6 -0
  138. package/dist/config/helpers.d.ts.map +1 -0
  139. package/dist/config/helpers.js +164 -0
  140. package/dist/config/helpers.js.map +1 -0
  141. package/dist/config/index.d.ts +15 -0
  142. package/dist/config/index.d.ts.map +1 -0
  143. package/dist/config/index.js +160 -0
  144. package/dist/config/index.js.map +1 -0
  145. package/dist/config/types.d.ts +57 -0
  146. package/dist/config/types.d.ts.map +1 -0
  147. package/dist/config/types.js +2 -0
  148. package/dist/config/types.js.map +1 -0
  149. package/dist/context.d.ts +8 -69
  150. package/dist/context.d.ts.map +1 -1
  151. package/dist/context.js +44 -24
  152. package/dist/context.js.map +1 -1
  153. package/dist/core/context.d.ts +66 -0
  154. package/dist/core/context.d.ts.map +1 -0
  155. package/dist/core/context.js +149 -0
  156. package/dist/core/context.js.map +1 -0
  157. package/dist/deep-agent.d.ts +5 -2
  158. package/dist/deep-agent.d.ts.map +1 -1
  159. package/dist/deep-agent.js +44 -11
  160. package/dist/deep-agent.js.map +1 -1
  161. package/dist/index.d.ts +6 -6
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +6 -6
  164. package/dist/index.js.map +1 -1
  165. package/dist/middleware/malformed-tool-call-middleware.d.ts +8 -0
  166. package/dist/middleware/malformed-tool-call-middleware.d.ts.map +1 -0
  167. package/dist/middleware/malformed-tool-call-middleware.js +191 -0
  168. package/dist/middleware/malformed-tool-call-middleware.js.map +1 -0
  169. package/dist/react-agent.d.ts +2 -2
  170. package/dist/react-agent.d.ts.map +1 -1
  171. package/dist/react-agent.js +28 -9
  172. package/dist/react-agent.js.map +1 -1
  173. package/package.json +1 -1
  174. package/scripts/resolve-deps.js +54 -0
  175. package/src/agents/deep-agent.ts +165 -0
  176. package/src/agents/react-agent.helpers.ts +227 -0
  177. package/src/agents/react-agent.ts +584 -0
  178. package/src/agents/sub-agent.ts +82 -0
  179. package/src/cli/args.ts +15 -0
  180. package/src/cli/event-listener.ts +162 -0
  181. package/src/cli/interactive.ts +144 -0
  182. package/src/cli/runtime.ts +31 -0
  183. package/src/cli/spinner.ts +23 -0
  184. package/src/cli/terminal-render.ts +322 -0
  185. package/src/cli/types.ts +33 -0
  186. package/src/cli.ts +91 -702
  187. package/src/config/helpers.ts +179 -0
  188. package/src/config/index.ts +245 -0
  189. package/src/config/types.ts +62 -0
  190. package/src/core/context.ts +266 -0
  191. package/src/index.ts +13 -11
  192. package/src/middleware/malformed-tool-call-middleware.ts +239 -0
  193. package/src/types/markdown-it-terminal.d.ts +4 -0
  194. package/src/types/marked-terminal.d.ts +16 -0
  195. package/dist/config.d.ts +0 -86
  196. package/dist/config.d.ts.map +0 -1
  197. package/dist/config.js +0 -84
  198. package/dist/config.js.map +0 -1
  199. package/src/config.ts +0 -177
  200. package/src/context.ts +0 -247
  201. package/src/deep-agent.ts +0 -104
  202. package/src/react-agent.ts +0 -576
  203. /package/{src → agent-runtime/src/middleware}/malformed-tool-call-middleware.ts +0 -0
  204. /package/{src → agent-runtime/src/types}/markdown-it-terminal.d.ts +0 -0
  205. /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,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
+ };
@@ -0,0 +1,82 @@
1
+ # iTermBot
2
+
3
+ iTermBot is an application built on the **@easynet** agent framework. It runs two agents:
4
+
5
+ 1. **ReAct agent** — LangChain `createAgent` (ReAct pattern) with tools and memory.
6
+ 2. **Deep agent** — DeepAgents `createDeepAgent` with a persistent store backed by agent-memory.
7
+
8
+ Both agents share:
9
+
10
+ - **@easynet/agent-common** — YAML config (app, paths).
11
+ - **@easynet/agent-model** — LLM and embedding models (falls back to module default config).
12
+ - **@easynet/agent-memory** — Agent memory (recall/inject for ReAct; store adapter for Deep).
13
+ - **@easynet/agent-tool** + **@easynet/agent-tool-buildin** — Tools (FS, HTTP, util, exec, etc.).
14
+
15
+ ## Prerequisites
16
+
17
+ - Node.js >= 18
18
+ - Ollama (or another OpenAI-compatible endpoint) for the LLM. Default config uses `http://localhost:11434/v1` and `qwen3:0.6b`.
19
+
20
+ ## Setup
21
+
22
+ Build from source workspace:
23
+
24
+ ```bash
25
+ cd apps/itermbot
26
+ npm install
27
+ npm run build
28
+ ```
29
+
30
+ Tool support uses agent-tool’s `@easynet/agent-tool` and `@easynet/agent-tool-buildin` from the npm registry.
31
+
32
+ ## Config
33
+
34
+ | File | Purpose |
35
+ |------|--------|
36
+ | `config/app.yaml` | App-level settings (`agent`, `printSteps`, prompt templates). |
37
+
38
+ Agent profile defaults (model/memory/tool/skills) are resolved by `@easynet/agent-runtime`.
39
+ Top-level app config only overrides runtime defaults.
40
+
41
+ Tool config now falls back to `@easynet/agent-tool` module defaults when app-level tool config is not provided.
42
+
43
+ ## Usage
44
+
45
+ - **Interactive (ReAct agent):**
46
+ ```bash
47
+ npm start
48
+ # or
49
+ npm run react
50
+ ```
51
+
52
+ - **Interactive (Deep agent):**
53
+ ```bash
54
+ npm run deep
55
+ ```
56
+
57
+ - **One-shot query:**
58
+ ```bash
59
+ node dist/index.js react "What time is it?"
60
+ node dist/index.js deep "Remember I prefer short answers."
61
+ ```
62
+
63
+ ## Scripts
64
+
65
+ | Script | Description |
66
+ |--------|-------------|
67
+ | `npm run build` | Compile TypeScript to `dist/`. |
68
+ | `npm start` | Run interactive with ReAct agent. |
69
+ | `npm run react` | Same as start (ReAct). |
70
+ | `npm run deep` | Interactive with Deep agent. |
71
+ | `npm run typecheck` | Type-check only. |
72
+ | `npm run test:llm` | Test LLM config (scripts/test-llm.mjs). |
73
+
74
+ ## Architecture
75
+
76
+ - **src/index.ts** — CLI startup and orchestration.
77
+ - **src/context.ts** — Shared `BotContext` builders (LLM/memory/tools/skills).
78
+ - **src/config.ts** — App-level override adapter on top of runtime config.
79
+ - **src/startup/** — startup UI, diagnostics, and panel color bootstrapping.
80
+ - **src/iterm/** — iTerm session routing and target session prompt injection.
81
+
82
+ Both agents use the same LLM, memory backend, and tool set; only the orchestration (ReAct vs Deep) differs.
@@ -0,0 +1,29 @@
1
+ apiVersion: easynet.world/v1
2
+ kind: AppConfig
3
+ metadata:
4
+ name: itermbot
5
+ spec:
6
+ agent: react
7
+
8
+ printSteps: false
9
+
10
+ promptTemplates:
11
+ itermPolicy: |
12
+ ## iTerm Operating Policy
13
+ - Target panel output is the remote source of truth.
14
+ - Never use local machine commands for system/project data collection.
15
+ - For remote operations/investigation, use `itermRunCommandInSession` in target panel.
16
+ - For current screen/panel analysis, never ask user to paste text; capture via no-op `:`.
17
+ - For full coverage, paginate with `outputOffsetLines + maxOutputLines`, summarize by chunk, then merge.
18
+ - If output is long, use bounded chunk analysis with interim summaries and one final conclusion.
19
+ - Prefer fast/low-cost commands; avoid heavy full scans/builds/tests unless required.
20
+ - Host may auto-update target panel when focus moves to a non-chat panel.
21
+ - Final response must be valid Markdown with stable formatting.
22
+ - Host may auto-recover target routing (reuse non-chat pane or auto-split); if still failing, ask user.
23
+ targetSession: |
24
+ ## Target Panel Session
25
+ Routed target panel (may change at runtime):
26
+ - sessionId: "{{sessionId}}"
27
+ - windowId: {{windowId}}
28
+ - tabIndex: {{tabIndex}}
29
+ Never use `windowId: 0` and never guess IDs.