@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,211 @@
1
+ "use strict";
2
+ // Azure DevOps API client.
3
+ // Provides a generic adoRequest() for arbitrary endpoints
4
+ // and a thin queryWorkItems() wrapper for backward compatibility.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.adoRequest = adoRequest;
7
+ exports.queryWorkItems = queryWorkItems;
8
+ exports.discoverOrganizations = discoverOrganizations;
9
+ exports.discoverProjects = discoverProjects;
10
+ const api_error_1 = require("../heart/api-error");
11
+ const runtime_1 = require("../nerves/runtime");
12
+ const ADO_BASE = "https://dev.azure.com";
13
+ const VSSPS_BASE = "https://app.vssps.visualstudio.com";
14
+ const DEFAULT_API_VERSION = "api-version=7.1";
15
+ // Append api-version=7.1 to the URL if not already present.
16
+ function ensureApiVersion(path) {
17
+ if (path.includes("api-version="))
18
+ return path;
19
+ return path.includes("?") ? `${path}&${DEFAULT_API_VERSION}` : `${path}?${DEFAULT_API_VERSION}`;
20
+ }
21
+ // Determine correct Content-Type for ADO requests.
22
+ function resolveContentType(method, path) {
23
+ const upper = method.toUpperCase();
24
+ const isWorkItemMutation = (upper === "POST" || upper === "PATCH") &&
25
+ path.toLowerCase().includes("/_apis/wit/workitems/");
26
+ return isWorkItemMutation
27
+ ? "application/json-patch+json"
28
+ : "application/json";
29
+ }
30
+ // Generic ADO API request. Returns response body as pretty-printed JSON string.
31
+ async function adoRequest(token, method, org, path, body) {
32
+ try {
33
+ (0, runtime_1.emitNervesEvent)({
34
+ event: "client.request_start",
35
+ component: "clients",
36
+ message: "starting ADO request",
37
+ meta: { client: "ado", method, org, path },
38
+ });
39
+ const fullPath = ensureApiVersion(path);
40
+ const url = `${ADO_BASE}/${org}${fullPath}`;
41
+ const contentType = resolveContentType(method, path);
42
+ const opts = {
43
+ method,
44
+ headers: {
45
+ Authorization: `Bearer ${token}`,
46
+ "Content-Type": contentType,
47
+ },
48
+ };
49
+ if (body)
50
+ opts.body = body;
51
+ const res = await fetch(url, opts);
52
+ if (!res.ok) {
53
+ (0, runtime_1.emitNervesEvent)({
54
+ level: "error",
55
+ event: "client.error",
56
+ component: "clients",
57
+ message: "ADO request failed",
58
+ meta: { client: "ado", method, org, path, status: res.status },
59
+ });
60
+ return (0, api_error_1.handleApiError)(res, "ADO", "ado");
61
+ }
62
+ const data = await res.json();
63
+ (0, runtime_1.emitNervesEvent)({
64
+ event: "client.request_end",
65
+ component: "clients",
66
+ message: "ADO request completed",
67
+ meta: { client: "ado", method, org, path, success: true },
68
+ });
69
+ return JSON.stringify(data, null, 2);
70
+ }
71
+ catch (err) {
72
+ (0, runtime_1.emitNervesEvent)({
73
+ level: "error",
74
+ event: "client.error",
75
+ component: "clients",
76
+ message: "ADO request threw exception",
77
+ meta: {
78
+ client: "ado",
79
+ method,
80
+ org,
81
+ path,
82
+ reason: err instanceof Error ? err.message : String(err),
83
+ },
84
+ });
85
+ return (0, api_error_1.handleApiError)(err, "ADO", "ado");
86
+ }
87
+ }
88
+ // Backward-compatible thin wrapper: runs WIQL query and returns formatted work items.
89
+ async function queryWorkItems(token, org, query) {
90
+ try {
91
+ (0, runtime_1.emitNervesEvent)({
92
+ event: "client.request_start",
93
+ component: "clients",
94
+ message: "starting ADO work item query",
95
+ meta: { client: "ado", org, operation: "queryWorkItems" },
96
+ });
97
+ // Step 1: Run WIQL query to get work item IDs
98
+ const wiqlRes = await fetch(`${ADO_BASE}/${org}/_apis/wit/wiql?${DEFAULT_API_VERSION}`, {
99
+ method: "POST",
100
+ headers: {
101
+ Authorization: `Bearer ${token}`,
102
+ "Content-Type": "application/json",
103
+ },
104
+ body: JSON.stringify({ query }),
105
+ });
106
+ if (!wiqlRes.ok) {
107
+ (0, runtime_1.emitNervesEvent)({
108
+ level: "error",
109
+ event: "client.error",
110
+ component: "clients",
111
+ message: "ADO WIQL query failed",
112
+ meta: { client: "ado", org, operation: "queryWorkItems", stage: "wiql", status: wiqlRes.status },
113
+ });
114
+ return (0, api_error_1.handleApiError)(wiqlRes, "ADO", "ado");
115
+ }
116
+ const wiqlData = (await wiqlRes.json());
117
+ if (!wiqlData.workItems || wiqlData.workItems.length === 0) {
118
+ (0, runtime_1.emitNervesEvent)({
119
+ event: "client.request_end",
120
+ component: "clients",
121
+ message: "ADO work item query returned no results",
122
+ meta: { client: "ado", org, operation: "queryWorkItems", count: 0 },
123
+ });
124
+ return "No work items found matching the query.";
125
+ }
126
+ // Step 2: Fetch work item details (batch, max 200)
127
+ const ids = wiqlData.workItems.slice(0, 200).map((wi) => wi.id);
128
+ const detailRes = await fetch(`${ADO_BASE}/${org}/_apis/wit/workitems?ids=${ids.join(",")}&${DEFAULT_API_VERSION}`, {
129
+ headers: {
130
+ Authorization: `Bearer ${token}`,
131
+ },
132
+ });
133
+ if (!detailRes.ok) {
134
+ (0, runtime_1.emitNervesEvent)({
135
+ level: "error",
136
+ event: "client.error",
137
+ component: "clients",
138
+ message: "ADO work item details fetch failed",
139
+ meta: { client: "ado", org, operation: "queryWorkItems", stage: "details", status: detailRes.status },
140
+ });
141
+ return (0, api_error_1.handleApiError)(detailRes, "ADO", "ado");
142
+ }
143
+ const detailData = (await detailRes.json());
144
+ // Format results
145
+ const lines = detailData.value.map((wi) => {
146
+ const assignedTo = wi.fields["System.AssignedTo"]?.displayName || "Unassigned";
147
+ return `#${wi.id}: ${wi.fields["System.Title"]} [${wi.fields["System.State"]}] (${assignedTo})`;
148
+ });
149
+ (0, runtime_1.emitNervesEvent)({
150
+ event: "client.request_end",
151
+ component: "clients",
152
+ message: "ADO work item query completed",
153
+ meta: { client: "ado", org, operation: "queryWorkItems", count: lines.length },
154
+ });
155
+ return lines.join("\n");
156
+ }
157
+ catch (err) {
158
+ (0, runtime_1.emitNervesEvent)({
159
+ level: "error",
160
+ event: "client.error",
161
+ component: "clients",
162
+ message: "ADO work item query threw exception",
163
+ meta: {
164
+ client: "ado",
165
+ org,
166
+ operation: "queryWorkItems",
167
+ reason: err instanceof Error ? err.message : String(err),
168
+ },
169
+ });
170
+ return (0, api_error_1.handleApiError)(err, "ADO", "ado");
171
+ }
172
+ }
173
+ // Discover ADO organizations accessible by the authenticated user.
174
+ // 1. Fetches user profile to get publicAlias (member ID)
175
+ // 2. Uses Accounts API to list organizations for that member
176
+ // Throws on API errors (callers handle error presentation).
177
+ async function discoverOrganizations(token) {
178
+ // Step 1: Get the user's publicAlias from their profile
179
+ const profileRes = await fetch(`${VSSPS_BASE}/_apis/profile/profiles/me?${DEFAULT_API_VERSION}`, {
180
+ headers: { Authorization: `Bearer ${token}` },
181
+ });
182
+ if (!profileRes.ok) {
183
+ throw new Error(`ADO profile request failed: ${profileRes.status} ${profileRes.statusText}`);
184
+ }
185
+ const profile = (await profileRes.json());
186
+ const memberId = profile.publicAlias;
187
+ if (!memberId) {
188
+ throw new Error("ADO profile response missing publicAlias");
189
+ }
190
+ // Step 2: List organizations for this member
191
+ const accountsRes = await fetch(`${VSSPS_BASE}/_apis/accounts?memberId=${memberId}&${DEFAULT_API_VERSION}`, {
192
+ headers: { Authorization: `Bearer ${token}` },
193
+ });
194
+ if (!accountsRes.ok) {
195
+ throw new Error(`ADO accounts request failed: ${accountsRes.status} ${accountsRes.statusText}`);
196
+ }
197
+ const data = (await accountsRes.json());
198
+ return (data.value ?? []).map((a) => a.accountName);
199
+ }
200
+ // Discover projects within an ADO organization.
201
+ // Throws on API errors (callers handle error presentation).
202
+ async function discoverProjects(token, org) {
203
+ const res = await fetch(`${ADO_BASE}/${org}/_apis/projects?${DEFAULT_API_VERSION}`, {
204
+ headers: { Authorization: `Bearer ${token}` },
205
+ });
206
+ if (!res.ok) {
207
+ throw new Error(`ADO projects request failed: ${res.status} ${res.statusText}`);
208
+ }
209
+ const data = (await res.json());
210
+ return (data.value ?? []).map((p) => p.name);
211
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ // ADO context helper -- shared by all semantic ADO tools.
3
+ // Extracts org/project from model-provided args or runs discovery cascade.
4
+ // Re-discovery on 403 naturally handled: scope discovery APIs reflect current access.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveAdoContext = resolveAdoContext;
7
+ const ado_client_1 = require("./ado-client");
8
+ const runtime_1 = require("../nerves/runtime");
9
+ /**
10
+ * Resolve ADO organization and project for a semantic tool.
11
+ * If org/project are provided by the model, use them directly.
12
+ * Otherwise, run discovery cascade: discover orgs, auto-select if single,
13
+ * then discover projects, auto-select if single.
14
+ *
15
+ * @param token - ADO OAuth token
16
+ * @param context - ResolvedContext from the context kernel
17
+ * @param args - optional org/project from the model
18
+ */
19
+ async function resolveAdoContext(token, context, args) {
20
+ (0, runtime_1.emitNervesEvent)({
21
+ component: "repertoire",
22
+ event: "repertoire.ado_context_resolve",
23
+ message: "resolving ado context",
24
+ meta: {},
25
+ });
26
+ // Reject if ADO integration is not available
27
+ if (!context.channel.availableIntegrations.includes("ado")) {
28
+ return { ok: false, error: "ADO integration is not available in this channel." };
29
+ }
30
+ try {
31
+ // Resolve organization
32
+ let org = args?.organization;
33
+ if (!org) {
34
+ const orgs = await (0, ado_client_1.discoverOrganizations)(token);
35
+ if (orgs.length === 0) {
36
+ return { ok: false, error: "No ADO organizations found for this user." };
37
+ }
38
+ if (orgs.length === 1) {
39
+ org = orgs[0];
40
+ }
41
+ else {
42
+ return {
43
+ ok: false,
44
+ error: `Multiple ADO organizations found. Please specify which one:\n${orgs.map(o => `- ${o}`).join("\n")}`,
45
+ };
46
+ }
47
+ }
48
+ // Resolve project
49
+ let project = args?.project;
50
+ if (!project) {
51
+ const projects = await (0, ado_client_1.discoverProjects)(token, org);
52
+ if (projects.length === 0) {
53
+ return { ok: false, error: `No projects found in organization "${org}".` };
54
+ }
55
+ if (projects.length === 1) {
56
+ project = projects[0];
57
+ }
58
+ else {
59
+ return {
60
+ ok: false,
61
+ error: `Multiple projects found in "${org}". Please specify which one:\n${projects.map(p => `- ${p}`).join("\n")}`,
62
+ };
63
+ }
64
+ }
65
+ return { ok: true, organization: org, project };
66
+ }
67
+ catch (err) {
68
+ return {
69
+ ok: false,
70
+ error: `error discovering ADO context: ${err instanceof Error ? err.message : String(err)}`,
71
+ };
72
+ }
73
+ }