@ouro.bot/cli 0.0.1-alpha.0 → 0.1.0-alpha.2

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 (119) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +20 -0
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +22 -0
  3. package/AdoptionSpecialist.ouro/psyche/identities/basilisk.md +31 -0
  4. package/AdoptionSpecialist.ouro/psyche/identities/jafar.md +31 -0
  5. package/AdoptionSpecialist.ouro/psyche/identities/jormungandr.md +31 -0
  6. package/AdoptionSpecialist.ouro/psyche/identities/kaa.md +31 -0
  7. package/AdoptionSpecialist.ouro/psyche/identities/medusa.md +31 -0
  8. package/AdoptionSpecialist.ouro/psyche/identities/monty.md +31 -0
  9. package/AdoptionSpecialist.ouro/psyche/identities/nagini.md +31 -0
  10. package/AdoptionSpecialist.ouro/psyche/identities/ouroboros.md +31 -0
  11. package/AdoptionSpecialist.ouro/psyche/identities/python.md +31 -0
  12. package/AdoptionSpecialist.ouro/psyche/identities/quetzalcoatl.md +31 -0
  13. package/AdoptionSpecialist.ouro/psyche/identities/sir-hiss.md +31 -0
  14. package/AdoptionSpecialist.ouro/psyche/identities/the-serpent.md +31 -0
  15. package/AdoptionSpecialist.ouro/psyche/identities/the-snake.md +31 -0
  16. package/README.md +224 -6
  17. package/dist/heart/agent-entry.js +17 -0
  18. package/dist/heart/api-error.js +34 -0
  19. package/dist/heart/config.js +296 -0
  20. package/dist/heart/core.js +515 -0
  21. package/dist/heart/daemon/daemon-cli.js +675 -0
  22. package/dist/heart/daemon/daemon-entry.js +74 -0
  23. package/dist/heart/daemon/daemon.js +313 -0
  24. package/dist/heart/daemon/hatch-flow.js +285 -0
  25. package/dist/heart/daemon/hatch-specialist.js +107 -0
  26. package/dist/heart/daemon/health-monitor.js +79 -0
  27. package/dist/heart/daemon/log-tailer.js +146 -0
  28. package/dist/heart/daemon/message-router.js +98 -0
  29. package/dist/heart/daemon/os-cron.js +260 -0
  30. package/dist/heart/daemon/ouro-bot-entry.js +23 -0
  31. package/dist/heart/daemon/ouro-bot-wrapper.js +90 -0
  32. package/dist/heart/daemon/ouro-entry.js +23 -0
  33. package/dist/heart/daemon/ouro-uti.js +212 -0
  34. package/dist/heart/daemon/process-manager.js +237 -0
  35. package/dist/heart/daemon/runtime-logging.js +98 -0
  36. package/dist/heart/daemon/subagent-installer.js +125 -0
  37. package/dist/heart/daemon/task-scheduler.js +240 -0
  38. package/dist/heart/harness.js +26 -0
  39. package/dist/heart/identity.js +281 -0
  40. package/dist/heart/kicks.js +144 -0
  41. package/dist/heart/primitives.js +4 -0
  42. package/dist/heart/providers/anthropic.js +329 -0
  43. package/dist/heart/providers/azure.js +66 -0
  44. package/dist/heart/providers/minimax.js +53 -0
  45. package/dist/heart/providers/openai-codex.js +162 -0
  46. package/dist/heart/streaming.js +412 -0
  47. package/dist/heart/turn-coordinator.js +62 -0
  48. package/dist/inner-worker-entry.js +4 -0
  49. package/dist/mind/associative-recall.js +197 -0
  50. package/dist/mind/bundle-manifest.js +118 -0
  51. package/dist/mind/context.js +302 -0
  52. package/dist/mind/first-impressions.js +43 -0
  53. package/dist/mind/format.js +56 -0
  54. package/dist/mind/friends/channel.js +41 -0
  55. package/dist/mind/friends/resolver.js +84 -0
  56. package/dist/mind/friends/store-file.js +171 -0
  57. package/dist/mind/friends/store.js +4 -0
  58. package/dist/mind/friends/tokens.js +26 -0
  59. package/dist/mind/friends/types.js +21 -0
  60. package/dist/mind/memory.js +388 -0
  61. package/dist/mind/pending.js +93 -0
  62. package/dist/mind/phrases.js +43 -0
  63. package/dist/mind/prompt-refresh.js +20 -0
  64. package/dist/mind/prompt.js +352 -0
  65. package/dist/mind/token-estimate.js +119 -0
  66. package/dist/nerves/cli-logging.js +31 -0
  67. package/dist/nerves/coverage/audit-rules.js +81 -0
  68. package/dist/nerves/coverage/audit.js +200 -0
  69. package/dist/nerves/coverage/cli-main.js +5 -0
  70. package/dist/nerves/coverage/cli.js +51 -0
  71. package/dist/nerves/coverage/contract.js +23 -0
  72. package/dist/nerves/coverage/file-completeness.js +56 -0
  73. package/dist/nerves/coverage/run-artifacts.js +77 -0
  74. package/dist/nerves/coverage/source-scanner.js +34 -0
  75. package/dist/nerves/index.js +152 -0
  76. package/dist/nerves/runtime.js +38 -0
  77. package/dist/repertoire/ado-client.js +211 -0
  78. package/dist/repertoire/ado-context.js +73 -0
  79. package/dist/repertoire/ado-semantic.js +841 -0
  80. package/dist/repertoire/ado-templates.js +146 -0
  81. package/dist/repertoire/coding/index.js +36 -0
  82. package/dist/repertoire/coding/manager.js +489 -0
  83. package/dist/repertoire/coding/monitor.js +60 -0
  84. package/dist/repertoire/coding/reporter.js +45 -0
  85. package/dist/repertoire/coding/spawner.js +102 -0
  86. package/dist/repertoire/coding/tools.js +167 -0
  87. package/dist/repertoire/coding/types.js +2 -0
  88. package/dist/repertoire/data/ado-endpoints.json +122 -0
  89. package/dist/repertoire/data/graph-endpoints.json +212 -0
  90. package/dist/repertoire/github-client.js +64 -0
  91. package/dist/repertoire/graph-client.js +118 -0
  92. package/dist/repertoire/skills.js +156 -0
  93. package/dist/repertoire/tasks/board.js +122 -0
  94. package/dist/repertoire/tasks/index.js +210 -0
  95. package/dist/repertoire/tasks/lifecycle.js +80 -0
  96. package/dist/repertoire/tasks/middleware.js +65 -0
  97. package/dist/repertoire/tasks/parser.js +173 -0
  98. package/dist/repertoire/tasks/scanner.js +132 -0
  99. package/dist/repertoire/tasks/transitions.js +145 -0
  100. package/dist/repertoire/tasks/types.js +2 -0
  101. package/dist/repertoire/tools-base.js +714 -0
  102. package/dist/repertoire/tools-github.js +53 -0
  103. package/dist/repertoire/tools-teams.js +308 -0
  104. package/dist/repertoire/tools.js +199 -0
  105. package/dist/senses/cli-entry.js +15 -0
  106. package/dist/senses/cli.js +604 -0
  107. package/dist/senses/commands.js +98 -0
  108. package/dist/senses/inner-dialog-worker.js +61 -0
  109. package/dist/senses/inner-dialog.js +231 -0
  110. package/dist/senses/session-lock.js +119 -0
  111. package/dist/senses/teams-entry.js +15 -0
  112. package/dist/senses/teams.js +696 -0
  113. package/dist/senses/trust-gate.js +150 -0
  114. package/package.json +34 -11
  115. package/subagents/README.md +73 -0
  116. package/subagents/work-doer.md +233 -0
  117. package/subagents/work-merger.md +624 -0
  118. package/subagents/work-planner.md +373 -0
  119. package/bin/ouro.js +0 -6
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.githubToolDefinitions = void 0;
4
+ exports.summarizeGithubArgs = summarizeGithubArgs;
5
+ const github_client_1 = require("./github-client");
6
+ const runtime_1 = require("../nerves/runtime");
7
+ exports.githubToolDefinitions = [
8
+ {
9
+ tool: {
10
+ type: "function",
11
+ function: {
12
+ name: "file_ouroboros_bug",
13
+ description: "File a bug or feature request on the ouroboros harness repo. Requires GitHub OAuth authorization.",
14
+ parameters: {
15
+ type: "object",
16
+ properties: {
17
+ title: { type: "string", description: "Issue title" },
18
+ body: { type: "string", description: "Issue body/description (optional)" },
19
+ labels: { type: "string", description: "Comma-separated label names (optional)" },
20
+ },
21
+ required: ["title"],
22
+ },
23
+ },
24
+ },
25
+ handler: async (args, ctx) => {
26
+ (0, runtime_1.emitNervesEvent)({
27
+ component: "repertoire",
28
+ event: "repertoire.github_tool_call",
29
+ message: "github tool invoked",
30
+ meta: {},
31
+ });
32
+ if (!ctx?.githubToken) {
33
+ return "AUTH_REQUIRED:github -- I need access to GitHub. Please sign in when prompted.";
34
+ }
35
+ const owner = "ouroborosbot";
36
+ const repo = "ouroboros";
37
+ const payload = { title: args.title };
38
+ if (args.body)
39
+ payload.body = args.body;
40
+ if (args.labels) {
41
+ payload.labels = args.labels.split(",").map((l) => l.trim());
42
+ }
43
+ return (0, github_client_1.githubRequest)(ctx.githubToken, "POST", `/repos/${owner}/${repo}/issues`, JSON.stringify(payload));
44
+ },
45
+ integration: "github",
46
+ confirmationRequired: true,
47
+ },
48
+ ];
49
+ function summarizeGithubArgs(name, args) {
50
+ if (name === "file_ouroboros_bug")
51
+ return args.title || "";
52
+ return undefined;
53
+ }
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.teamsToolHandlers = exports.teamsTools = exports.teamsToolDefinitions = void 0;
7
+ exports.summarizeTeamsArgs = summarizeTeamsArgs;
8
+ const graph_client_1 = require("./graph-client");
9
+ const ado_client_1 = require("./ado-client");
10
+ const graph_endpoints_json_1 = __importDefault(require("./data/graph-endpoints.json"));
11
+ const ado_endpoints_json_1 = __importDefault(require("./data/ado-endpoints.json"));
12
+ const runtime_1 = require("../nerves/runtime");
13
+ const MUTATE_METHODS = ["POST", "PATCH", "DELETE"];
14
+ // Map HTTP method to authority action name for canWrite() checks
15
+ const METHOD_TO_ACTION = {
16
+ POST: "createWorkItem",
17
+ PATCH: "updateWorkItem",
18
+ DELETE: "deleteWorkItem",
19
+ };
20
+ // Check if a tool response indicates a 403 PERMISSION_DENIED (authority checker removed; this is now a no-op kept for call-site stability)
21
+ function checkAndRecord403(_result, _integration, _scope, _action, _ctx) {
22
+ // No-op: AuthorityChecker eliminated. 403 recording removed.
23
+ }
24
+ const DEFAULT_ADO_QUERY = "SELECT [System.Id], [System.Title], [System.State], [System.AssignedTo] FROM WorkItems WHERE [System.AssignedTo] = @Me AND [System.State] <> 'Closed' ORDER BY [System.ChangedDate] DESC";
25
+ exports.teamsToolDefinitions = [
26
+ // -- Generic Graph tools --
27
+ {
28
+ tool: {
29
+ type: "function",
30
+ function: {
31
+ name: "graph_query",
32
+ description: "GET any Microsoft Graph API endpoint. Use graph_docs first to look up the correct path.",
33
+ parameters: {
34
+ type: "object",
35
+ properties: {
36
+ path: { type: "string", description: "Graph API path after /v1.0, e.g. /me/messages?$top=5" },
37
+ },
38
+ required: ["path"],
39
+ },
40
+ },
41
+ },
42
+ handler: async (args, ctx) => {
43
+ if (!ctx?.graphToken) {
44
+ return "AUTH_REQUIRED:graph -- I need access to Microsoft Graph. Please sign in when prompted.";
45
+ }
46
+ return (0, graph_client_1.graphRequest)(ctx.graphToken, "GET", args.path);
47
+ },
48
+ integration: "graph",
49
+ },
50
+ {
51
+ tool: {
52
+ type: "function",
53
+ function: {
54
+ name: "graph_mutate",
55
+ description: "POST/PATCH/DELETE any Microsoft Graph API endpoint. Use graph_docs first to look up the correct path.",
56
+ parameters: {
57
+ type: "object",
58
+ properties: {
59
+ method: { type: "string", enum: ["POST", "PATCH", "DELETE"], description: "HTTP method" },
60
+ path: { type: "string", description: "Graph API path after /v1.0" },
61
+ body: { type: "string", description: "JSON request body (optional)" },
62
+ },
63
+ required: ["method", "path"],
64
+ },
65
+ },
66
+ },
67
+ handler: async (args, ctx) => {
68
+ if (!ctx?.graphToken) {
69
+ return "AUTH_REQUIRED:graph -- I need access to Microsoft Graph. Please sign in when prompted.";
70
+ }
71
+ if (!MUTATE_METHODS.includes(args.method)) {
72
+ return `Invalid method "${args.method}". Must be one of: ${MUTATE_METHODS.join(", ")}`;
73
+ }
74
+ return (0, graph_client_1.graphRequest)(ctx.graphToken, args.method, args.path, args.body);
75
+ },
76
+ integration: "graph",
77
+ confirmationRequired: true,
78
+ },
79
+ // -- Generic ADO tools --
80
+ {
81
+ tool: {
82
+ type: "function",
83
+ function: {
84
+ name: "ado_query",
85
+ description: "GET or POST (for WIQL read queries) any Azure DevOps API endpoint. Use ado_docs first to look up the correct path.",
86
+ parameters: {
87
+ type: "object",
88
+ properties: {
89
+ organization: { type: "string", description: "Azure DevOps organization name" },
90
+ path: { type: "string", description: "ADO API path after /{org}, e.g. /_apis/wit/wiql" },
91
+ method: { type: "string", enum: ["GET", "POST"], description: "HTTP method (defaults to GET)" },
92
+ body: { type: "string", description: "JSON request body (optional, used with POST for WIQL)" },
93
+ },
94
+ required: ["organization", "path"],
95
+ },
96
+ },
97
+ },
98
+ handler: async (args, ctx) => {
99
+ if (!ctx?.adoToken) {
100
+ return "AUTH_REQUIRED:ado -- I need access to Azure DevOps. Please sign in when prompted.";
101
+ }
102
+ const method = args.method || "GET";
103
+ const result = await (0, ado_client_1.adoRequest)(ctx.adoToken, method, args.organization, args.path, args.body);
104
+ checkAndRecord403(result, "ado", args.organization, method, ctx);
105
+ return result;
106
+ },
107
+ integration: "ado",
108
+ },
109
+ {
110
+ tool: {
111
+ type: "function",
112
+ function: {
113
+ name: "ado_mutate",
114
+ description: "POST/PATCH/DELETE any Azure DevOps API endpoint for actual mutations. Use ado_docs first to look up the correct path.",
115
+ parameters: {
116
+ type: "object",
117
+ properties: {
118
+ method: { type: "string", enum: ["POST", "PATCH", "DELETE"], description: "HTTP method" },
119
+ organization: { type: "string", description: "Azure DevOps organization name" },
120
+ path: { type: "string", description: "ADO API path after /{org}" },
121
+ body: { type: "string", description: "JSON request body (optional)" },
122
+ },
123
+ required: ["method", "organization", "path"],
124
+ },
125
+ },
126
+ },
127
+ handler: async (args, ctx) => {
128
+ if (!ctx?.adoToken) {
129
+ return "AUTH_REQUIRED:ado -- I need access to Azure DevOps. Please sign in when prompted.";
130
+ }
131
+ if (!MUTATE_METHODS.includes(args.method)) {
132
+ return `Invalid method "${args.method}". Must be one of: ${MUTATE_METHODS.join(", ")}`;
133
+ }
134
+ /* v8 ignore next -- fallback unreachable: method is validated against MUTATE_METHODS above @preserve */
135
+ const action = METHOD_TO_ACTION[args.method] || args.method;
136
+ const result = await (0, ado_client_1.adoRequest)(ctx.adoToken, args.method, args.organization, args.path, args.body);
137
+ checkAndRecord403(result, "ado", args.organization, action, ctx);
138
+ return result;
139
+ },
140
+ integration: "ado",
141
+ confirmationRequired: true,
142
+ },
143
+ // -- Convenience aliases (backward compat) --
144
+ {
145
+ tool: {
146
+ type: "function",
147
+ function: {
148
+ name: "graph_profile",
149
+ description: "get the current user's Microsoft 365 profile (name, email, job title, department, office location)",
150
+ parameters: { type: "object", properties: {} },
151
+ },
152
+ },
153
+ handler: async (_args, ctx) => {
154
+ if (!ctx?.graphToken) {
155
+ return "AUTH_REQUIRED:graph -- I need access to your Microsoft 365 profile. Please sign in when prompted.";
156
+ }
157
+ return (0, graph_client_1.getProfile)(ctx.graphToken);
158
+ },
159
+ integration: "graph",
160
+ },
161
+ {
162
+ tool: {
163
+ type: "function",
164
+ function: {
165
+ name: "ado_work_items",
166
+ description: "query or list Azure DevOps work items. provide an organization and optionally a WIQL query. if organization is omitted, discovers available organizations automatically.",
167
+ parameters: {
168
+ type: "object",
169
+ properties: {
170
+ organization: { type: "string", description: "Azure DevOps organization name (optional -- omit to discover)" },
171
+ query: { type: "string", description: "WIQL query (optional, defaults to recent assigned work items)" },
172
+ },
173
+ },
174
+ },
175
+ },
176
+ handler: async (args, ctx) => {
177
+ if (!ctx?.adoToken) {
178
+ return "AUTH_REQUIRED:ado -- I need access to your Azure DevOps account. Please sign in when prompted.";
179
+ }
180
+ let org = args.organization;
181
+ if (!org) {
182
+ // Discovery cascade: discover orgs, auto-select if single, disambiguate otherwise
183
+ try {
184
+ const orgs = await (0, ado_client_1.discoverOrganizations)(ctx.adoToken);
185
+ if (orgs.length === 0) {
186
+ return "No ADO organizations found for your account. Ensure your Azure DevOps account has access to at least one organization.";
187
+ }
188
+ if (orgs.length === 1) {
189
+ org = orgs[0];
190
+ }
191
+ else {
192
+ return `Multiple ADO organizations found. Please specify which organization to use:\n${orgs.map((o) => `- ${o}`).join("\n")}`;
193
+ }
194
+ }
195
+ catch (e) {
196
+ return `error discovering ADO organizations: ${e instanceof Error ? e.message : String(e)}`;
197
+ }
198
+ }
199
+ const query = args.query || DEFAULT_ADO_QUERY;
200
+ return (0, ado_client_1.queryWorkItems)(ctx.adoToken, org, query);
201
+ },
202
+ integration: "ado",
203
+ },
204
+ // -- Documentation tools --
205
+ {
206
+ tool: {
207
+ type: "function",
208
+ function: {
209
+ name: "graph_docs",
210
+ description: "Search the Microsoft Graph API endpoint index. Use before calling graph_query or graph_mutate to find the correct path, method, and required scopes.",
211
+ parameters: {
212
+ type: "object",
213
+ properties: {
214
+ query: { type: "string", description: "Search query, e.g. 'send email' or 'calendar events'" },
215
+ },
216
+ required: ["query"],
217
+ },
218
+ },
219
+ },
220
+ handler: (args) => {
221
+ return searchEndpoints(graph_endpoints_json_1.default, args.query || "");
222
+ },
223
+ integration: "graph",
224
+ },
225
+ {
226
+ tool: {
227
+ type: "function",
228
+ function: {
229
+ name: "ado_docs",
230
+ description: "Search the Azure DevOps API endpoint index. Use before calling ado_query or ado_mutate to find the correct path, method, and parameters.",
231
+ parameters: {
232
+ type: "object",
233
+ properties: {
234
+ query: { type: "string", description: "Search query, e.g. 'work items' or 'pull requests'" },
235
+ },
236
+ required: ["query"],
237
+ },
238
+ },
239
+ },
240
+ handler: (args) => {
241
+ return searchEndpoints(ado_endpoints_json_1.default, args.query || "");
242
+ },
243
+ integration: "ado",
244
+ },
245
+ ];
246
+ // Backward-compat: extract just the OpenAI tool schemas
247
+ exports.teamsTools = exports.teamsToolDefinitions.map((d) => d.tool);
248
+ // Backward-compat: extract just the handlers by name
249
+ exports.teamsToolHandlers = Object.fromEntries(exports.teamsToolDefinitions.map((d) => [d.tool.function.name, d.handler]));
250
+ function searchEndpoints(entries, query) {
251
+ (0, runtime_1.emitNervesEvent)({
252
+ component: "repertoire",
253
+ event: "repertoire.endpoint_search",
254
+ message: "searching endpoint index",
255
+ meta: {},
256
+ });
257
+ const q = query.toLowerCase();
258
+ const matches = entries.filter((e) => {
259
+ const haystack = `${e.description} ${e.path}`.toLowerCase();
260
+ return haystack.includes(q);
261
+ });
262
+ if (matches.length === 0) {
263
+ return `No matching endpoints found for "${query}". Try a broader search term.`;
264
+ }
265
+ return matches.slice(0, 5).map((e) => {
266
+ const lines = [
267
+ `${e.method} ${e.path}`,
268
+ ` ${e.description}`,
269
+ ` Params: ${e.params || "none"}`,
270
+ ];
271
+ if (e.scopes)
272
+ lines.push(` Scopes: ${e.scopes}`);
273
+ return lines.join("\n");
274
+ }).join("\n\n");
275
+ }
276
+ function summarizeTeamsArgs(name, args) {
277
+ function summarizeKeyValues(keys) {
278
+ const parts = [];
279
+ for (const key of keys) {
280
+ const raw = args[key];
281
+ if (raw === undefined || raw === null)
282
+ continue;
283
+ const compact = String(raw).replace(/\s+/g, " ").trim();
284
+ if (!compact)
285
+ continue;
286
+ const clipped = compact.length > 60 ? compact.slice(0, 60) + "..." : compact;
287
+ parts.push(`${key}=${clipped}`);
288
+ }
289
+ return parts.join(" ");
290
+ }
291
+ if (name === "graph_profile")
292
+ return "";
293
+ if (name === "ado_work_items")
294
+ return summarizeKeyValues(["organization", "query"]);
295
+ if (name === "graph_query")
296
+ return summarizeKeyValues(["path"]);
297
+ if (name === "graph_mutate")
298
+ return summarizeKeyValues(["method", "path"]);
299
+ if (name === "ado_query")
300
+ return summarizeKeyValues(["method", "organization", "path"]);
301
+ if (name === "ado_mutate")
302
+ return summarizeKeyValues(["method", "organization", "path"]);
303
+ if (name === "graph_docs")
304
+ return summarizeKeyValues(["query"]);
305
+ if (name === "ado_docs")
306
+ return summarizeKeyValues(["query"]);
307
+ return undefined;
308
+ }
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.teamsTools = exports.finalAnswerTool = exports.tools = void 0;
4
+ exports.getToolsForChannel = getToolsForChannel;
5
+ exports.isConfirmationRequired = isConfirmationRequired;
6
+ exports.execTool = execTool;
7
+ exports.summarizeArgs = summarizeArgs;
8
+ const tools_base_1 = require("./tools-base");
9
+ const tools_teams_1 = require("./tools-teams");
10
+ const ado_semantic_1 = require("./ado-semantic");
11
+ const tools_github_1 = require("./tools-github");
12
+ const runtime_1 = require("../nerves/runtime");
13
+ // Re-export types and constants used by the rest of the codebase
14
+ var tools_base_2 = require("./tools-base");
15
+ Object.defineProperty(exports, "tools", { enumerable: true, get: function () { return tools_base_2.tools; } });
16
+ Object.defineProperty(exports, "finalAnswerTool", { enumerable: true, get: function () { return tools_base_2.finalAnswerTool; } });
17
+ var tools_teams_2 = require("./tools-teams");
18
+ Object.defineProperty(exports, "teamsTools", { enumerable: true, get: function () { return tools_teams_2.teamsTools; } });
19
+ // All tool definitions in a single registry
20
+ const allDefinitions = [...tools_base_1.baseToolDefinitions, ...tools_teams_1.teamsToolDefinitions, ...ado_semantic_1.adoSemanticToolDefinitions, ...tools_github_1.githubToolDefinitions];
21
+ const REMOTE_BLOCKED_LOCAL_TOOLS = new Set(["shell", "read_file", "write_file", "git_commit", "gh_cli"]);
22
+ function baseToolsForCapabilities(capabilities) {
23
+ const isRemoteChannel = capabilities?.channel === "teams";
24
+ if (!isRemoteChannel)
25
+ return tools_base_1.tools;
26
+ return tools_base_1.tools.filter((tool) => !REMOTE_BLOCKED_LOCAL_TOOLS.has(tool.function.name));
27
+ }
28
+ // Apply a single tool preference to a tool schema, returning a new object.
29
+ function applyPreference(tool, pref) {
30
+ return {
31
+ ...tool,
32
+ function: {
33
+ ...tool.function,
34
+ description: `${tool.function.description}\n\nfriend preference: ${pref}`,
35
+ },
36
+ };
37
+ }
38
+ // Return the appropriate tools list based on channel capabilities.
39
+ // Base tools (no integration) are always included.
40
+ // Teams/integration tools are included only if their integration is in availableIntegrations.
41
+ // When toolPreferences is provided, matching preferences are appended to tool descriptions.
42
+ function getToolsForChannel(capabilities, toolPreferences) {
43
+ const baseTools = baseToolsForCapabilities(capabilities);
44
+ if (!capabilities || capabilities.availableIntegrations.length === 0) {
45
+ return baseTools;
46
+ }
47
+ const available = new Set(capabilities.availableIntegrations);
48
+ const integrationDefs = [...tools_teams_1.teamsToolDefinitions, ...ado_semantic_1.adoSemanticToolDefinitions, ...tools_github_1.githubToolDefinitions].filter((d) => d.integration && available.has(d.integration));
49
+ if (!toolPreferences || Object.keys(toolPreferences).length === 0) {
50
+ return [...baseTools, ...integrationDefs.map((d) => d.tool)];
51
+ }
52
+ // Build a map of integration -> preference text for fast lookup
53
+ const prefMap = new Map();
54
+ for (const [key, value] of Object.entries(toolPreferences)) {
55
+ prefMap.set(key, value);
56
+ }
57
+ // Apply preferences to matching integration tools (new objects, no mutation)
58
+ // d.integration is guaranteed truthy -- integrationDefs are pre-filtered above
59
+ const enrichedIntegrationTools = integrationDefs.map((d) => {
60
+ const pref = prefMap.get(d.integration);
61
+ return pref ? applyPreference(d.tool, pref) : d.tool;
62
+ });
63
+ return [...baseTools, ...enrichedIntegrationTools];
64
+ }
65
+ // Check whether a tool requires user confirmation before execution.
66
+ // Reads from ToolDefinition.confirmationRequired instead of a separate Set.
67
+ function isConfirmationRequired(toolName) {
68
+ const def = allDefinitions.find((d) => d.tool.function.name === toolName);
69
+ return def?.confirmationRequired === true;
70
+ }
71
+ async function execTool(name, args, ctx) {
72
+ (0, runtime_1.emitNervesEvent)({
73
+ event: "tool.start",
74
+ component: "tools",
75
+ message: "tool execution started",
76
+ meta: { name },
77
+ });
78
+ // Look up from combined registry
79
+ const def = allDefinitions.find((d) => d.tool.function.name === name);
80
+ if (!def) {
81
+ (0, runtime_1.emitNervesEvent)({
82
+ level: "error",
83
+ event: "tool.error",
84
+ component: "tools",
85
+ message: "unknown tool requested",
86
+ meta: { name },
87
+ });
88
+ return `unknown: ${name}`;
89
+ }
90
+ const isRemoteChannel = ctx?.context?.channel?.channel === "teams";
91
+ if (isRemoteChannel && REMOTE_BLOCKED_LOCAL_TOOLS.has(name)) {
92
+ const message = "I can't do that from here because I'm talking to multiple people in a shared remote channel, and local shell/file/git/gh operations could let conversations interfere with each other. Ask me for a remote-safe alternative (Graph/ADO/web), or run that operation from CLI.";
93
+ (0, runtime_1.emitNervesEvent)({
94
+ level: "warn",
95
+ event: "tool.error",
96
+ component: "tools",
97
+ message: "blocked local tool in remote channel",
98
+ meta: { name, channel: "teams" },
99
+ });
100
+ return message;
101
+ }
102
+ try {
103
+ const result = await def.handler(args, ctx);
104
+ (0, runtime_1.emitNervesEvent)({
105
+ event: "tool.end",
106
+ component: "tools",
107
+ message: "tool execution finished",
108
+ meta: { name, success: true },
109
+ });
110
+ return result;
111
+ }
112
+ catch (error) {
113
+ (0, runtime_1.emitNervesEvent)({
114
+ level: "error",
115
+ event: "tool.error",
116
+ component: "tools",
117
+ message: error instanceof Error ? error.message : String(error),
118
+ meta: { name },
119
+ });
120
+ throw error;
121
+ }
122
+ }
123
+ function summarizeKeyValues(args, keys, maxValueLength = 60) {
124
+ const parts = [];
125
+ for (const key of keys) {
126
+ const raw = args[key];
127
+ if (raw === undefined || raw === null)
128
+ continue;
129
+ const compact = String(raw).replace(/\s+/g, " ").trim();
130
+ if (!compact)
131
+ continue;
132
+ const clipped = compact.length > maxValueLength ? compact.slice(0, maxValueLength) + "..." : compact;
133
+ parts.push(`${key}=${clipped}`);
134
+ }
135
+ return parts.join(" ");
136
+ }
137
+ function summarizeUnknownArgs(args) {
138
+ const keys = Object.keys(args);
139
+ if (keys.length === 0)
140
+ return "";
141
+ return summarizeKeyValues(args, keys);
142
+ }
143
+ function summarizeArgs(name, args) {
144
+ // Check teams tools first
145
+ const teamsSummary = (0, tools_teams_1.summarizeTeamsArgs)(name, args);
146
+ if (teamsSummary !== undefined)
147
+ return teamsSummary;
148
+ // Check github tools
149
+ const githubSummary = (0, tools_github_1.summarizeGithubArgs)(name, args);
150
+ if (githubSummary !== undefined)
151
+ return githubSummary;
152
+ // Base tools
153
+ if (name === "read_file" || name === "write_file")
154
+ return summarizeKeyValues(args, ["path"]);
155
+ if (name === "shell")
156
+ return summarizeKeyValues(args, ["command"]);
157
+ if (name === "list_directory")
158
+ return summarizeKeyValues(args, ["path"]);
159
+ if (name === "git_commit")
160
+ return summarizeKeyValues(args, ["message"]);
161
+ if (name === "gh_cli")
162
+ return summarizeKeyValues(args, ["command"]);
163
+ if (name === "load_skill")
164
+ return summarizeKeyValues(args, ["name"]);
165
+ if (name === "task_create")
166
+ return summarizeKeyValues(args, ["title", "type", "category"]);
167
+ if (name === "task_update_status")
168
+ return summarizeKeyValues(args, ["name", "status"]);
169
+ if (name === "task_board_status")
170
+ return summarizeKeyValues(args, ["status"]);
171
+ if (name === "task_board_action")
172
+ return summarizeKeyValues(args, ["scope"]);
173
+ if (name === "task_board" || name === "task_board_deps" || name === "task_board_sessions")
174
+ return "";
175
+ if (name === "coding_spawn")
176
+ return summarizeKeyValues(args, ["runner", "workdir", "taskRef"]);
177
+ if (name === "coding_status")
178
+ return summarizeKeyValues(args, ["sessionId"]);
179
+ if (name === "coding_send_input")
180
+ return summarizeKeyValues(args, ["sessionId", "input"]);
181
+ if (name === "coding_kill")
182
+ return summarizeKeyValues(args, ["sessionId"]);
183
+ if (name === "claude")
184
+ return summarizeKeyValues(args, ["prompt"]);
185
+ if (name === "web_search")
186
+ return summarizeKeyValues(args, ["query"]);
187
+ if (name === "memory_search")
188
+ return summarizeKeyValues(args, ["query"]);
189
+ if (name === "memory_save")
190
+ return summarizeKeyValues(args, ["text", "about"]);
191
+ if (name === "get_friend_note")
192
+ return summarizeKeyValues(args, ["friendId"]);
193
+ if (name === "save_friend_note") {
194
+ return summarizeKeyValues(args, ["type", "key", "content"]);
195
+ }
196
+ if (name === "ado_backlog_list")
197
+ return summarizeKeyValues(args, ["organization", "project"]);
198
+ return summarizeUnknownArgs(args);
199
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ // Thin entrypoint for `npm run dev` / `node dist/senses/cli-entry.js --agent <name>`.
3
+ // Separated from cli.ts so the CLI adapter is pure library code with clean
4
+ // 100% test coverage -- entrypoints can't be covered by vitest since
5
+ // require.main !== module in the test runner.
6
+ // All config comes from the conventional ~/.agentsecrets/<agent>/secrets.json path.
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ // Fail fast if --agent is missing (before any src/ code tries getAgentName())
9
+ if (!process.argv.includes("--agent")) {
10
+ // eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
11
+ console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/cli-entry.js --agent ouroboros");
12
+ process.exit(1);
13
+ }
14
+ const cli_1 = require("./cli");
15
+ (0, cli_1.main)();