@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.
- package/deploy/stack-manifests/v0.9.json +96 -16
- package/dist/bin/agentic-ontology-backfill.js +6 -0
- package/dist/bin/agentic-reflection-backfill.js +6 -0
- package/dist/bin/agentic-semantic-label.js +6 -0
- package/dist/bin/backfill-conversations.js +6 -0
- package/dist/bin/backfill-responses.js +6 -0
- package/dist/bin/backfill-vectors.js +6 -0
- package/dist/bin/bulk-sync-postgres.js +6 -0
- package/dist/bin/cleanup-stale-review-tasks.js +6 -0
- package/dist/bin/cli.js +1257 -178
- package/dist/bin/exe-agent.js +6 -0
- package/dist/bin/exe-assign.js +6 -0
- package/dist/bin/exe-boot.js +6 -0
- package/dist/bin/exe-call.js +6 -0
- package/dist/bin/exe-cloud.js +6 -0
- package/dist/bin/exe-dispatch.js +6 -0
- package/dist/bin/exe-doctor.js +6 -0
- package/dist/bin/exe-export-behaviors.js +6 -0
- package/dist/bin/exe-forget.js +6 -0
- package/dist/bin/exe-gateway.js +151 -110
- package/dist/bin/exe-heartbeat.js +6 -0
- package/dist/bin/exe-kill.js +6 -0
- package/dist/bin/exe-launch-agent.js +6 -0
- package/dist/bin/exe-new-employee.js +6 -0
- package/dist/bin/exe-pending-messages.js +6 -0
- package/dist/bin/exe-pending-notifications.js +6 -0
- package/dist/bin/exe-pending-reviews.js +6 -0
- package/dist/bin/exe-rename.js +13 -4
- package/dist/bin/exe-review.js +6 -0
- package/dist/bin/exe-search.js +6 -0
- package/dist/bin/exe-session-cleanup.js +6 -0
- package/dist/bin/exe-start-codex.js +6 -0
- package/dist/bin/exe-start-opencode.js +6 -0
- package/dist/bin/exe-status.js +6 -0
- package/dist/bin/exe-team.js +6 -0
- package/dist/bin/git-sweep.js +6 -0
- package/dist/bin/graph-backfill.js +150 -110
- package/dist/bin/graph-export.js +6 -0
- package/dist/bin/intercom-check.js +6 -0
- package/dist/bin/registry-proxy.js +207 -0
- package/dist/bin/scan-tasks.js +6 -0
- package/dist/bin/setup.js +6 -0
- package/dist/bin/shard-migrate.js +6 -0
- package/dist/bin/stack-update.js +128 -0
- package/dist/gateway/index.js +151 -110
- package/dist/hooks/bug-report-worker.js +6 -0
- package/dist/hooks/codex-stop-task-finalizer.js +6 -0
- package/dist/hooks/commit-complete.js +6 -0
- package/dist/hooks/error-recall.js +6 -0
- package/dist/hooks/ingest.js +6 -0
- package/dist/hooks/instructions-loaded.js +6 -0
- package/dist/hooks/notification.js +6 -0
- package/dist/hooks/post-compact.js +6 -0
- package/dist/hooks/post-tool-combined.js +6 -0
- package/dist/hooks/pre-compact.js +6 -0
- package/dist/hooks/pre-tool-use.js +6 -0
- package/dist/hooks/prompt-submit.js +6 -0
- package/dist/hooks/session-end.js +6 -0
- package/dist/hooks/session-start.js +6 -0
- package/dist/hooks/stop.js +6 -0
- package/dist/hooks/subagent-stop.js +6 -0
- package/dist/hooks/summary-worker.js +6 -0
- package/dist/index.js +151 -110
- package/dist/lib/employee-templates.js +6 -0
- package/dist/lib/exe-daemon.js +382 -234
- package/dist/lib/hybrid-search.js +6 -0
- package/dist/lib/registry-proxy.js +162 -0
- package/dist/lib/schedules.js +6 -0
- package/dist/lib/store.js +6 -0
- package/dist/mcp/server.js +318 -222
- package/dist/runtime/index.js +6 -0
- package/dist/tui/App.js +6 -0
- package/package.json +3 -2
- package/stack.release.json +6 -4
- 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
|
+
};
|
package/dist/lib/schedules.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",
|
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",
|