@askexenow/exe-os 0.9.69 → 0.9.70

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 (75) hide show
  1. package/deploy/stack-manifests/v0.9.json +96 -16
  2. package/dist/bin/agentic-ontology-backfill.js +6 -0
  3. package/dist/bin/agentic-reflection-backfill.js +6 -0
  4. package/dist/bin/agentic-semantic-label.js +6 -0
  5. package/dist/bin/backfill-conversations.js +6 -0
  6. package/dist/bin/backfill-responses.js +6 -0
  7. package/dist/bin/backfill-vectors.js +6 -0
  8. package/dist/bin/bulk-sync-postgres.js +6 -0
  9. package/dist/bin/cleanup-stale-review-tasks.js +6 -0
  10. package/dist/bin/cli.js +1257 -178
  11. package/dist/bin/exe-agent.js +6 -0
  12. package/dist/bin/exe-assign.js +6 -0
  13. package/dist/bin/exe-boot.js +6 -0
  14. package/dist/bin/exe-call.js +6 -0
  15. package/dist/bin/exe-cloud.js +6 -0
  16. package/dist/bin/exe-dispatch.js +6 -0
  17. package/dist/bin/exe-doctor.js +6 -0
  18. package/dist/bin/exe-export-behaviors.js +6 -0
  19. package/dist/bin/exe-forget.js +6 -0
  20. package/dist/bin/exe-gateway.js +151 -110
  21. package/dist/bin/exe-heartbeat.js +6 -0
  22. package/dist/bin/exe-kill.js +6 -0
  23. package/dist/bin/exe-launch-agent.js +6 -0
  24. package/dist/bin/exe-new-employee.js +6 -0
  25. package/dist/bin/exe-pending-messages.js +6 -0
  26. package/dist/bin/exe-pending-notifications.js +6 -0
  27. package/dist/bin/exe-pending-reviews.js +6 -0
  28. package/dist/bin/exe-rename.js +13 -4
  29. package/dist/bin/exe-review.js +6 -0
  30. package/dist/bin/exe-search.js +6 -0
  31. package/dist/bin/exe-session-cleanup.js +6 -0
  32. package/dist/bin/exe-start-codex.js +6 -0
  33. package/dist/bin/exe-start-opencode.js +6 -0
  34. package/dist/bin/exe-status.js +6 -0
  35. package/dist/bin/exe-team.js +6 -0
  36. package/dist/bin/git-sweep.js +6 -0
  37. package/dist/bin/graph-backfill.js +150 -110
  38. package/dist/bin/graph-export.js +6 -0
  39. package/dist/bin/intercom-check.js +6 -0
  40. package/dist/bin/registry-proxy.js +207 -0
  41. package/dist/bin/scan-tasks.js +6 -0
  42. package/dist/bin/setup.js +6 -0
  43. package/dist/bin/shard-migrate.js +6 -0
  44. package/dist/bin/stack-update.js +128 -0
  45. package/dist/gateway/index.js +151 -110
  46. package/dist/hooks/bug-report-worker.js +6 -0
  47. package/dist/hooks/codex-stop-task-finalizer.js +6 -0
  48. package/dist/hooks/commit-complete.js +6 -0
  49. package/dist/hooks/error-recall.js +6 -0
  50. package/dist/hooks/ingest.js +6 -0
  51. package/dist/hooks/instructions-loaded.js +6 -0
  52. package/dist/hooks/notification.js +6 -0
  53. package/dist/hooks/post-compact.js +6 -0
  54. package/dist/hooks/post-tool-combined.js +6 -0
  55. package/dist/hooks/pre-compact.js +6 -0
  56. package/dist/hooks/pre-tool-use.js +6 -0
  57. package/dist/hooks/prompt-submit.js +6 -0
  58. package/dist/hooks/session-end.js +6 -0
  59. package/dist/hooks/session-start.js +6 -0
  60. package/dist/hooks/stop.js +6 -0
  61. package/dist/hooks/subagent-stop.js +6 -0
  62. package/dist/hooks/summary-worker.js +6 -0
  63. package/dist/index.js +151 -110
  64. package/dist/lib/employee-templates.js +6 -0
  65. package/dist/lib/exe-daemon.js +382 -234
  66. package/dist/lib/hybrid-search.js +6 -0
  67. package/dist/lib/registry-proxy.js +162 -0
  68. package/dist/lib/schedules.js +6 -0
  69. package/dist/lib/store.js +6 -0
  70. package/dist/mcp/server.js +318 -222
  71. package/dist/runtime/index.js +6 -0
  72. package/dist/tui/App.js +6 -0
  73. package/package.json +3 -2
  74. package/stack.release.json +6 -4
  75. package/stack.release.schema.json +89 -18
@@ -4123,6 +4123,12 @@ var init_platform_procedures = __esm({
4123
4123
  priority: "p0",
4124
4124
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
4125
4125
  },
4126
+ {
4127
+ title: "Code context first for repository orientation",
4128
+ domain: "workflow",
4129
+ priority: "p1",
4130
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
4131
+ },
4126
4132
  {
4127
4133
  title: "Commit discipline \u2014 never leave verified work floating",
4128
4134
  domain: "workflow",
@@ -0,0 +1,162 @@
1
+ // src/lib/registry-proxy.ts
2
+ import { createServer } from "http";
3
+ import { Readable } from "stream";
4
+ function parsePullTokens(raw) {
5
+ return (raw ?? "").split(/[\n,]/).map((s) => s.trim()).filter(Boolean);
6
+ }
7
+ function registryProxyOptionsFromEnv(env = process.env) {
8
+ const upstreamToken = env.EXE_REGISTRY_PROXY_UPSTREAM_TOKEN || env.GHCR_TOKEN || "";
9
+ const pullTokens = parsePullTokens(env.EXE_REGISTRY_PROXY_PULL_TOKENS);
10
+ return {
11
+ port: Number(env.EXE_REGISTRY_PROXY_PORT || 3201),
12
+ host: env.EXE_REGISTRY_PROXY_HOST || "0.0.0.0",
13
+ upstream: env.EXE_REGISTRY_PROXY_UPSTREAM || "https://ghcr.io",
14
+ upstreamUsername: env.EXE_REGISTRY_PROXY_UPSTREAM_USERNAME || env.GHCR_USERNAME || "askexe",
15
+ upstreamToken,
16
+ pullTokens,
17
+ allowedNamespace: env.EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE || "askexe"
18
+ };
19
+ }
20
+ function assertRegistryProxyConfig(options) {
21
+ if (!options.upstreamToken) throw new Error("EXE_REGISTRY_PROXY_UPSTREAM_TOKEN or GHCR_TOKEN is required");
22
+ if (options.pullTokens.length === 0) throw new Error("EXE_REGISTRY_PROXY_PULL_TOKENS is required");
23
+ if (!options.allowedNamespace || !/^[a-z0-9._-]+$/i.test(options.allowedNamespace)) {
24
+ throw new Error("EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE must be a registry-safe namespace");
25
+ }
26
+ }
27
+ function timingSafeIncludes(values, candidate) {
28
+ return values.some((value) => value === candidate);
29
+ }
30
+ function parseBasicAuth(header) {
31
+ if (!header?.startsWith("Basic ")) return null;
32
+ try {
33
+ const decoded = Buffer.from(header.slice("Basic ".length), "base64").toString("utf8");
34
+ const idx = decoded.indexOf(":");
35
+ if (idx < 0) return null;
36
+ return { username: decoded.slice(0, idx), password: decoded.slice(idx + 1) };
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
41
+ function unauthorized(res) {
42
+ res.writeHead(401, {
43
+ "www-authenticate": 'Basic realm="AskExe Registry Proxy"',
44
+ "content-type": "application/json"
45
+ });
46
+ res.end(JSON.stringify({ error: "registry proxy authentication required" }));
47
+ }
48
+ function isAllowedPath(pathname, namespace) {
49
+ if (pathname === "/health") return true;
50
+ if (pathname === "/v2/" || pathname === "/v2") return true;
51
+ const prefix = `/v2/${namespace}/`;
52
+ if (!pathname.startsWith(prefix)) return false;
53
+ if (pathname.includes("..") || /%2f/i.test(pathname)) return false;
54
+ return true;
55
+ }
56
+ function parseBearerChallenge(header) {
57
+ if (!header?.toLowerCase().startsWith("bearer ")) return null;
58
+ const raw = header.slice("Bearer ".length);
59
+ const params = new URLSearchParams();
60
+ for (const part of raw.match(/(?:[^,"]+|"[^"]*")+/g) ?? []) {
61
+ const idx = part.indexOf("=");
62
+ if (idx < 0) continue;
63
+ const key = part.slice(0, idx).trim();
64
+ const value = part.slice(idx + 1).trim().replace(/^"|"$/g, "");
65
+ params.set(key, value);
66
+ }
67
+ const realm = params.get("realm");
68
+ if (!realm) return null;
69
+ params.delete("realm");
70
+ return { realm, params };
71
+ }
72
+ async function fetchUpstreamWithRegistryAuth(url, init, upstreamBasicAuth) {
73
+ const firstHeaders = new Headers(init.headers);
74
+ firstHeaders.set("authorization", `Basic ${upstreamBasicAuth}`);
75
+ const first = await fetch(url, { ...init, headers: firstHeaders });
76
+ if (first.status !== 401) return first;
77
+ const challenge = parseBearerChallenge(first.headers.get("www-authenticate"));
78
+ if (!challenge) return first;
79
+ const tokenUrl = new URL(challenge.realm);
80
+ for (const [key, value] of challenge.params.entries()) tokenUrl.searchParams.set(key, value);
81
+ const tokenRes = await fetch(tokenUrl, { headers: { authorization: `Basic ${upstreamBasicAuth}` } });
82
+ if (!tokenRes.ok) return first;
83
+ const tokenJson = await tokenRes.json();
84
+ const token = tokenJson.token ?? tokenJson.access_token;
85
+ if (!token) return first;
86
+ const retryHeaders = new Headers(init.headers);
87
+ retryHeaders.set("authorization", `Bearer ${token}`);
88
+ return fetch(url, { ...init, headers: retryHeaders });
89
+ }
90
+ function copyResponseHeaders(from, to) {
91
+ for (const [key, value] of from.entries()) {
92
+ const lower = key.toLowerCase();
93
+ if (["connection", "keep-alive", "transfer-encoding", "content-encoding"].includes(lower)) continue;
94
+ to.setHeader(key, value);
95
+ }
96
+ }
97
+ function createRegistryProxyServer(options) {
98
+ assertRegistryProxyConfig(options);
99
+ const upstream = new URL(options.upstream ?? "https://ghcr.io");
100
+ const namespace = options.allowedNamespace ?? "askexe";
101
+ const upstreamAuth = Buffer.from(`${options.upstreamUsername ?? "askexe"}:${options.upstreamToken}`).toString("base64");
102
+ return createServer(async (req, res) => {
103
+ const requestUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
104
+ if (requestUrl.pathname === "/health") {
105
+ res.writeHead(200, { "content-type": "application/json" });
106
+ res.end(JSON.stringify({ ok: true, service: "exe-registry-proxy", upstream: upstream.origin, namespace }));
107
+ return;
108
+ }
109
+ if (!isAllowedPath(requestUrl.pathname, namespace)) {
110
+ res.writeHead(404, { "content-type": "application/json" });
111
+ res.end(JSON.stringify({ error: "registry path not allowed" }));
112
+ return;
113
+ }
114
+ const auth = parseBasicAuth(req.headers.authorization);
115
+ if (!auth || !timingSafeIncludes(options.pullTokens, auth.password)) {
116
+ unauthorized(res);
117
+ return;
118
+ }
119
+ const upstreamUrl = new URL(requestUrl.pathname + requestUrl.search, upstream.origin);
120
+ const headers = new Headers();
121
+ for (const [key, value] of Object.entries(req.headers)) {
122
+ if (!value) continue;
123
+ const lower = key.toLowerCase();
124
+ if (["host", "connection", "authorization", "content-length"].includes(lower)) continue;
125
+ headers.set(key, Array.isArray(value) ? value.join(",") : value);
126
+ }
127
+ headers.set("authorization", `Basic ${upstreamAuth}`);
128
+ try {
129
+ const upstreamRes = await fetchUpstreamWithRegistryAuth(upstreamUrl, {
130
+ method: req.method,
131
+ headers,
132
+ body: req.method === "GET" || req.method === "HEAD" ? void 0 : req,
133
+ // Required by undici when streaming request bodies.
134
+ duplex: "half"
135
+ }, upstreamAuth);
136
+ res.statusCode = upstreamRes.status;
137
+ res.statusMessage = upstreamRes.statusText;
138
+ copyResponseHeaders(upstreamRes.headers, res);
139
+ if (!upstreamRes.body || req.method === "HEAD") {
140
+ res.end();
141
+ return;
142
+ }
143
+ Readable.fromWeb(upstreamRes.body).pipe(res);
144
+ } catch (err) {
145
+ res.writeHead(502, { "content-type": "application/json" });
146
+ res.end(JSON.stringify({ error: "upstream registry proxy failed", detail: err instanceof Error ? err.message : String(err) }));
147
+ }
148
+ });
149
+ }
150
+ async function runRegistryProxy(options = registryProxyOptionsFromEnv()) {
151
+ const server = createRegistryProxyServer(options);
152
+ await new Promise((resolve) => server.listen(options.port, options.host, resolve));
153
+ console.log(`exe-registry-proxy listening on ${options.host ?? "0.0.0.0"}:${options.port}`);
154
+ console.log(`proxying /v2/${options.allowedNamespace ?? "askexe"}/* -> ${options.upstream ?? "https://ghcr.io"}`);
155
+ }
156
+ export {
157
+ assertRegistryProxyConfig,
158
+ createRegistryProxyServer,
159
+ parsePullTokens,
160
+ registryProxyOptionsFromEnv,
161
+ runRegistryProxy
162
+ };
@@ -3352,6 +3352,12 @@ var init_platform_procedures = __esm({
3352
3352
  priority: "p0",
3353
3353
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
3354
3354
  },
3355
+ {
3356
+ title: "Code context first for repository orientation",
3357
+ domain: "workflow",
3358
+ priority: "p1",
3359
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
3360
+ },
3355
3361
  {
3356
3362
  title: "Commit discipline \u2014 never leave verified work floating",
3357
3363
  domain: "workflow",
package/dist/lib/store.js CHANGED
@@ -3352,6 +3352,12 @@ var init_platform_procedures = __esm({
3352
3352
  priority: "p0",
3353
3353
  content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
3354
3354
  },
3355
+ {
3356
+ title: "Code context first for repository orientation",
3357
+ domain: "workflow",
3358
+ priority: "p1",
3359
+ content: "Before broad repo exploration, symbol tracing, blast-radius review, or codebase Q&A, agents should use the consolidated code_context MCP tool instead of manual grep/read loops. Use action=index or stats to refresh/check the index; action=search with query, limit, offset, languages, paths, refresh_index for fresh multi-language code/doc search; action=trace for symbol imports/dependents; action=blast_radius for impact analysis before edits. CLI parity exists via exe-os code-context init|index|status|stats|search|doctor. Keep code_context separate from durable employee memory: promote only validated decisions, procedures, or lessons into store_memory/commit_memory."
3360
+ },
3355
3361
  {
3356
3362
  title: "Commit discipline \u2014 never leave verified work floating",
3357
3363
  domain: "workflow",