@askexenow/exe-os 0.9.69 → 0.9.71
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 +33 -0
- package/dist/bin/agentic-reflection-backfill.js +33 -0
- package/dist/bin/agentic-semantic-label.js +33 -0
- package/dist/bin/backfill-conversations.js +33 -0
- package/dist/bin/backfill-responses.js +33 -0
- package/dist/bin/backfill-vectors.js +33 -0
- package/dist/bin/bulk-sync-postgres.js +33 -0
- package/dist/bin/cleanup-stale-review-tasks.js +33 -0
- package/dist/bin/cli.js +1284 -178
- package/dist/bin/exe-agent.js +6 -0
- package/dist/bin/exe-assign.js +33 -0
- package/dist/bin/exe-boot.js +33 -0
- package/dist/bin/exe-call.js +6 -0
- package/dist/bin/exe-cloud.js +33 -0
- package/dist/bin/exe-dispatch.js +33 -0
- package/dist/bin/exe-doctor.js +33 -0
- package/dist/bin/exe-export-behaviors.js +33 -0
- package/dist/bin/exe-forget.js +33 -0
- package/dist/bin/exe-gateway.js +178 -110
- package/dist/bin/exe-heartbeat.js +33 -0
- package/dist/bin/exe-kill.js +33 -0
- package/dist/bin/exe-launch-agent.js +33 -0
- package/dist/bin/exe-new-employee.js +6 -0
- package/dist/bin/exe-pending-messages.js +33 -0
- package/dist/bin/exe-pending-notifications.js +33 -0
- package/dist/bin/exe-pending-reviews.js +33 -0
- package/dist/bin/exe-rename.js +40 -4
- package/dist/bin/exe-review.js +33 -0
- package/dist/bin/exe-search.js +33 -0
- package/dist/bin/exe-session-cleanup.js +33 -0
- package/dist/bin/exe-start-codex.js +33 -0
- package/dist/bin/exe-start-opencode.js +33 -0
- package/dist/bin/exe-status.js +33 -0
- package/dist/bin/exe-team.js +33 -0
- package/dist/bin/git-sweep.js +33 -0
- package/dist/bin/graph-backfill.js +177 -110
- package/dist/bin/graph-export.js +33 -0
- package/dist/bin/intercom-check.js +33 -0
- package/dist/bin/registry-proxy.js +207 -0
- package/dist/bin/scan-tasks.js +33 -0
- package/dist/bin/setup.js +33 -0
- package/dist/bin/shard-migrate.js +33 -0
- package/dist/bin/stack-update.js +128 -0
- package/dist/gateway/index.js +178 -110
- package/dist/hooks/bug-report-worker.js +33 -0
- package/dist/hooks/codex-stop-task-finalizer.js +33 -0
- package/dist/hooks/commit-complete.js +33 -0
- package/dist/hooks/error-recall.js +33 -0
- package/dist/hooks/ingest.js +33 -0
- package/dist/hooks/instructions-loaded.js +33 -0
- package/dist/hooks/notification.js +33 -0
- package/dist/hooks/post-compact.js +33 -0
- package/dist/hooks/post-tool-combined.js +698 -17
- package/dist/hooks/pre-compact.js +33 -0
- package/dist/hooks/pre-tool-use.js +33 -0
- package/dist/hooks/prompt-submit.js +314 -0
- package/dist/hooks/session-end.js +33 -0
- package/dist/hooks/session-start.js +33 -0
- package/dist/hooks/stop.js +279 -12
- package/dist/hooks/subagent-stop.js +33 -0
- package/dist/hooks/summary-worker.js +33 -0
- package/dist/index.js +178 -110
- package/dist/lib/cloud-sync.js +27 -0
- package/dist/lib/database.js +27 -0
- package/dist/lib/db.js +27 -0
- package/dist/lib/device-registry.js +27 -0
- package/dist/lib/employee-templates.js +6 -0
- package/dist/lib/exe-daemon.js +639 -259
- package/dist/lib/hybrid-search.js +33 -0
- package/dist/lib/registry-proxy.js +162 -0
- package/dist/lib/schedules.js +33 -0
- package/dist/lib/store.js +33 -0
- package/dist/mcp/server.js +561 -244
- package/dist/runtime/index.js +33 -0
- package/dist/tui/App.js +33 -0
- package/package.json +3 -2
- package/stack.release.json +6 -4
- package/stack.release.schema.json +89 -18
package/dist/bin/scan-tasks.js
CHANGED
|
@@ -3038,6 +3038,33 @@ async function ensureSchema() {
|
|
|
3038
3038
|
CREATE INDEX IF NOT EXISTS idx_chat_history_session
|
|
3039
3039
|
ON chat_history(session_id, id);
|
|
3040
3040
|
`);
|
|
3041
|
+
await client.executeMultiple(`
|
|
3042
|
+
CREATE TABLE IF NOT EXISTS session_events (
|
|
3043
|
+
id TEXT PRIMARY KEY,
|
|
3044
|
+
agent_id TEXT NOT NULL,
|
|
3045
|
+
agent_role TEXT NOT NULL,
|
|
3046
|
+
session_id TEXT NOT NULL,
|
|
3047
|
+
session_scope TEXT,
|
|
3048
|
+
project_name TEXT NOT NULL,
|
|
3049
|
+
event_index INTEGER NOT NULL,
|
|
3050
|
+
event_type TEXT NOT NULL,
|
|
3051
|
+
tool_name TEXT,
|
|
3052
|
+
tool_use_id TEXT,
|
|
3053
|
+
content TEXT NOT NULL,
|
|
3054
|
+
payload_json TEXT,
|
|
3055
|
+
has_error INTEGER NOT NULL DEFAULT 0,
|
|
3056
|
+
created_at TEXT NOT NULL
|
|
3057
|
+
);
|
|
3058
|
+
|
|
3059
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
|
|
3060
|
+
ON session_events(agent_id, created_at DESC);
|
|
3061
|
+
|
|
3062
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_session_index
|
|
3063
|
+
ON session_events(session_id, event_index);
|
|
3064
|
+
|
|
3065
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
|
|
3066
|
+
ON session_events(session_scope, agent_id, created_at DESC);
|
|
3067
|
+
`);
|
|
3041
3068
|
await client.executeMultiple(`
|
|
3042
3069
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
3043
3070
|
id TEXT PRIMARY KEY,
|
|
@@ -7912,6 +7939,12 @@ var init_platform_procedures = __esm({
|
|
|
7912
7939
|
priority: "p0",
|
|
7913
7940
|
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."
|
|
7914
7941
|
},
|
|
7942
|
+
{
|
|
7943
|
+
title: "Code context first for repository orientation",
|
|
7944
|
+
domain: "workflow",
|
|
7945
|
+
priority: "p1",
|
|
7946
|
+
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."
|
|
7947
|
+
},
|
|
7915
7948
|
{
|
|
7916
7949
|
title: "Commit discipline \u2014 never leave verified work floating",
|
|
7917
7950
|
domain: "workflow",
|
package/dist/bin/setup.js
CHANGED
|
@@ -3841,6 +3841,33 @@ async function ensureSchema() {
|
|
|
3841
3841
|
CREATE INDEX IF NOT EXISTS idx_chat_history_session
|
|
3842
3842
|
ON chat_history(session_id, id);
|
|
3843
3843
|
`);
|
|
3844
|
+
await client.executeMultiple(`
|
|
3845
|
+
CREATE TABLE IF NOT EXISTS session_events (
|
|
3846
|
+
id TEXT PRIMARY KEY,
|
|
3847
|
+
agent_id TEXT NOT NULL,
|
|
3848
|
+
agent_role TEXT NOT NULL,
|
|
3849
|
+
session_id TEXT NOT NULL,
|
|
3850
|
+
session_scope TEXT,
|
|
3851
|
+
project_name TEXT NOT NULL,
|
|
3852
|
+
event_index INTEGER NOT NULL,
|
|
3853
|
+
event_type TEXT NOT NULL,
|
|
3854
|
+
tool_name TEXT,
|
|
3855
|
+
tool_use_id TEXT,
|
|
3856
|
+
content TEXT NOT NULL,
|
|
3857
|
+
payload_json TEXT,
|
|
3858
|
+
has_error INTEGER NOT NULL DEFAULT 0,
|
|
3859
|
+
created_at TEXT NOT NULL
|
|
3860
|
+
);
|
|
3861
|
+
|
|
3862
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
|
|
3863
|
+
ON session_events(agent_id, created_at DESC);
|
|
3864
|
+
|
|
3865
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_session_index
|
|
3866
|
+
ON session_events(session_id, event_index);
|
|
3867
|
+
|
|
3868
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
|
|
3869
|
+
ON session_events(session_scope, agent_id, created_at DESC);
|
|
3870
|
+
`);
|
|
3844
3871
|
await client.executeMultiple(`
|
|
3845
3872
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
3846
3873
|
id TEXT PRIMARY KEY,
|
|
@@ -6411,6 +6438,12 @@ var init_platform_procedures = __esm({
|
|
|
6411
6438
|
priority: "p0",
|
|
6412
6439
|
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."
|
|
6413
6440
|
},
|
|
6441
|
+
{
|
|
6442
|
+
title: "Code context first for repository orientation",
|
|
6443
|
+
domain: "workflow",
|
|
6444
|
+
priority: "p1",
|
|
6445
|
+
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."
|
|
6446
|
+
},
|
|
6414
6447
|
{
|
|
6415
6448
|
title: "Commit discipline \u2014 never leave verified work floating",
|
|
6416
6449
|
domain: "workflow",
|
|
@@ -2222,6 +2222,33 @@ async function ensureSchema() {
|
|
|
2222
2222
|
CREATE INDEX IF NOT EXISTS idx_chat_history_session
|
|
2223
2223
|
ON chat_history(session_id, id);
|
|
2224
2224
|
`);
|
|
2225
|
+
await client.executeMultiple(`
|
|
2226
|
+
CREATE TABLE IF NOT EXISTS session_events (
|
|
2227
|
+
id TEXT PRIMARY KEY,
|
|
2228
|
+
agent_id TEXT NOT NULL,
|
|
2229
|
+
agent_role TEXT NOT NULL,
|
|
2230
|
+
session_id TEXT NOT NULL,
|
|
2231
|
+
session_scope TEXT,
|
|
2232
|
+
project_name TEXT NOT NULL,
|
|
2233
|
+
event_index INTEGER NOT NULL,
|
|
2234
|
+
event_type TEXT NOT NULL,
|
|
2235
|
+
tool_name TEXT,
|
|
2236
|
+
tool_use_id TEXT,
|
|
2237
|
+
content TEXT NOT NULL,
|
|
2238
|
+
payload_json TEXT,
|
|
2239
|
+
has_error INTEGER NOT NULL DEFAULT 0,
|
|
2240
|
+
created_at TEXT NOT NULL
|
|
2241
|
+
);
|
|
2242
|
+
|
|
2243
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
|
|
2244
|
+
ON session_events(agent_id, created_at DESC);
|
|
2245
|
+
|
|
2246
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_session_index
|
|
2247
|
+
ON session_events(session_id, event_index);
|
|
2248
|
+
|
|
2249
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
|
|
2250
|
+
ON session_events(session_scope, agent_id, created_at DESC);
|
|
2251
|
+
`);
|
|
2225
2252
|
await client.executeMultiple(`
|
|
2226
2253
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
2227
2254
|
id TEXT PRIMARY KEY,
|
|
@@ -3353,6 +3380,12 @@ var init_platform_procedures = __esm({
|
|
|
3353
3380
|
priority: "p0",
|
|
3354
3381
|
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."
|
|
3355
3382
|
},
|
|
3383
|
+
{
|
|
3384
|
+
title: "Code context first for repository orientation",
|
|
3385
|
+
domain: "workflow",
|
|
3386
|
+
priority: "p1",
|
|
3387
|
+
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."
|
|
3388
|
+
},
|
|
3356
3389
|
{
|
|
3357
3390
|
title: "Commit discipline \u2014 never leave verified work floating",
|
|
3358
3391
|
domain: "workflow",
|
package/dist/bin/stack-update.js
CHANGED
|
@@ -150,6 +150,102 @@ function createStackUpdatePlan(manifest, envRaw, targetVersion) {
|
|
|
150
150
|
breakingChanges: release.breakingChanges ?? []
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
+
var ASKEXE_GHCR_IMAGE = /^(?:ghcr\.io\/askexe|registry\.askexe\.com\/askexe)\/[a-z0-9._/-]+(?::[^:@$/{]+|@sha256:[a-f0-9]{64})$/i;
|
|
154
|
+
function validatePinnedGhcrImage(image, label) {
|
|
155
|
+
const trimmed = image.trim().replace(/^['"]|['"]$/g, "");
|
|
156
|
+
if (!trimmed) return `${label} is empty`;
|
|
157
|
+
if (trimmed.includes("${")) return null;
|
|
158
|
+
if (!trimmed.startsWith("ghcr.io/askexe/") && !trimmed.startsWith("registry.askexe.com/askexe/")) return `${label} must use ghcr.io/askexe/* or registry.askexe.com/askexe/*, got ${trimmed}`;
|
|
159
|
+
if (/:latest(?:$|[\s#])/.test(trimmed)) return `${label} must not use :latest (${trimmed})`;
|
|
160
|
+
if (!ASKEXE_GHCR_IMAGE.test(trimmed)) return `${label} must be pinned with an explicit tag or sha256 digest from ghcr.io/askexe or registry.askexe.com/askexe, got ${trimmed}`;
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
function validateComposeImageLiteral(image, label) {
|
|
164
|
+
const trimmed = image.trim().replace(/^['"]|['"]$/g, "");
|
|
165
|
+
if (!trimmed) return `${label} is empty`;
|
|
166
|
+
if (trimmed.startsWith("ghcr.io/askexe/") || trimmed.startsWith("registry.askexe.com/askexe/")) return validatePinnedGhcrImage(trimmed, label);
|
|
167
|
+
if (/^(postgres|pgvector\/pgvector|clickhouse\/clickhouse-server|redis|nginx|postgrest\/postgrest|supabase\/gotrue):[^:]+$/i.test(trimmed)) return null;
|
|
168
|
+
return `${label} uses unsupported non-AskExe image ${trimmed}; customer app images must come from pinned ghcr.io/askexe images`;
|
|
169
|
+
}
|
|
170
|
+
function collectProductionDeployGateIssues(plan, envRaw, composeRaw) {
|
|
171
|
+
const issues = [];
|
|
172
|
+
const env = parseEnv(envRaw);
|
|
173
|
+
for (const [serviceName, service] of Object.entries(plan.release.services)) {
|
|
174
|
+
const manifestIssue = validatePinnedGhcrImage(service.image, `manifest ${plan.targetVersion}.${serviceName}.image`);
|
|
175
|
+
if (manifestIssue) issues.push({ kind: "manifest-image", message: manifestIssue });
|
|
176
|
+
const envImage = env.get(service.env);
|
|
177
|
+
if (envImage) {
|
|
178
|
+
const envIssue = validatePinnedGhcrImage(envImage, `env ${service.env}`);
|
|
179
|
+
if (envIssue) issues.push({ kind: "env-image", message: envIssue });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const lines = composeRaw.split(/\r?\n/);
|
|
183
|
+
lines.forEach((line, index) => {
|
|
184
|
+
if (/^\s*build\s*:/.test(line)) {
|
|
185
|
+
issues.push({ kind: "compose-build", message: `compose line ${index + 1} contains build:, production deploys must pull images` });
|
|
186
|
+
}
|
|
187
|
+
const imageMatch = line.match(/^\s*image\s*:\s*(.+?)\s*(?:#.*)?$/);
|
|
188
|
+
if (imageMatch) {
|
|
189
|
+
const image = imageMatch[1].trim();
|
|
190
|
+
if (image.includes("${")) {
|
|
191
|
+
const fallback = image.match(/:-([^}]+)}/)?.[1];
|
|
192
|
+
if (fallback) {
|
|
193
|
+
const composeIssue = validateComposeImageLiteral(fallback, `compose image fallback on line ${index + 1}`);
|
|
194
|
+
if (composeIssue) issues.push({ kind: "compose-image", message: composeIssue });
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
const composeIssue = validateComposeImageLiteral(image, `compose image on line ${index + 1}`);
|
|
198
|
+
if (composeIssue) issues.push({ kind: "compose-image", message: composeIssue });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
return issues;
|
|
203
|
+
}
|
|
204
|
+
function assertDeploymentScopeAllowed(plan, persona = "customer") {
|
|
205
|
+
if (persona === "askexe-control-plane") return;
|
|
206
|
+
const blocked = Object.entries(plan.release.services).filter(([, service]) => service.deploymentScope === "askexe-control-plane").map(([name]) => name);
|
|
207
|
+
if (blocked.length > 0) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`Customer deployment manifest includes AskExe control-plane service(s): ${blocked.join(", ")}. Customer VPSs may deploy customer services and optional agents only.`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function assertProductionDeployGate(plan, envRaw, composeRaw, options = {}) {
|
|
214
|
+
const issues = collectProductionDeployGateIssues(plan, envRaw, composeRaw);
|
|
215
|
+
if (issues.length === 0) return;
|
|
216
|
+
if (options.breakGlassReason?.trim()) {
|
|
217
|
+
writeBreakGlassAudit(plan, issues, options);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const details = issues.map((issue) => `- [${issue.kind}] ${issue.message}`).join("\n");
|
|
221
|
+
throw new Error(
|
|
222
|
+
`Production deploy gate failed. Exe OS deploys must use pinned ghcr.io/askexe or registry.askexe.com/askexe images and must not build from source on the VPS.
|
|
223
|
+
${details}
|
|
224
|
+
Emergency override requires --break-glass <reason> and writes an audit file.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
function writeBreakGlassAudit(plan, issues, options) {
|
|
228
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
229
|
+
const stamp = now().toISOString().replace(/[:.]/g, "-");
|
|
230
|
+
const defaultDir = existsSync("exe/output") ? "exe/output" : path.dirname(options.envFile ?? ".");
|
|
231
|
+
const auditFile = options.breakGlassAuditFile ?? path.join(defaultDir, `stack-update-break-glass-${stamp}.md`);
|
|
232
|
+
mkdirSync(path.dirname(auditFile), { recursive: true });
|
|
233
|
+
const body = [
|
|
234
|
+
`# Stack Update Break-Glass Audit \u2014 ${now().toISOString()}`,
|
|
235
|
+
"",
|
|
236
|
+
`Target version: ${plan.targetVersion}`,
|
|
237
|
+
`Reason: ${options.breakGlassReason?.trim()}`,
|
|
238
|
+
"",
|
|
239
|
+
"## Gate failures overridden",
|
|
240
|
+
...issues.map((issue) => `- [${issue.kind}] ${issue.message}`),
|
|
241
|
+
"",
|
|
242
|
+
"## Required follow-up",
|
|
243
|
+
"Return this deployment to the standard pinned GHCR image path immediately after the emergency is resolved.",
|
|
244
|
+
""
|
|
245
|
+
].join("\n");
|
|
246
|
+
writeFileSync(auditFile, body, { mode: 384 });
|
|
247
|
+
console.warn(`[stack-update] BREAK-GLASS deploy override recorded: ${auditFile}`);
|
|
248
|
+
}
|
|
153
249
|
function assertBreakingChangesAllowed(plan, allowedIds) {
|
|
154
250
|
const required = plan.breakingChanges.filter((c) => c.requiresConfirmation !== false);
|
|
155
251
|
const missing = required.filter((c) => !allowedIds.includes(c.id));
|
|
@@ -172,6 +268,15 @@ async function runStackUpdate(options) {
|
|
|
172
268
|
const envRaw = readFileSync(options.envFile, "utf8");
|
|
173
269
|
const plan = createStackUpdatePlan(manifest, envRaw, options.targetVersion);
|
|
174
270
|
assertBreakingChangesAllowed(plan, options.allowedBreakingChangeIds ?? []);
|
|
271
|
+
assertDeploymentScopeAllowed(plan, options.deploymentPersona ?? "customer");
|
|
272
|
+
const plannedEnvRaw = patchEnv(envRaw, Object.fromEntries(plan.changes.map((c) => [c.key, c.after])));
|
|
273
|
+
const composeRaw = readFileSync(options.composeFile, "utf8");
|
|
274
|
+
assertProductionDeployGate(plan, plannedEnvRaw, composeRaw, {
|
|
275
|
+
breakGlassReason: options.breakGlassReason,
|
|
276
|
+
breakGlassAuditFile: options.breakGlassAuditFile,
|
|
277
|
+
now,
|
|
278
|
+
envFile: options.envFile
|
|
279
|
+
});
|
|
175
280
|
const lockFile = options.lockFile ?? path.join(path.dirname(options.envFile), ".exe-stack-lock.json");
|
|
176
281
|
const previousVersion = readCurrentStackVersion(lockFile);
|
|
177
282
|
if (options.dryRun || plan.changes.length === 0) {
|
|
@@ -360,6 +465,7 @@ function parseArgs(args) {
|
|
|
360
465
|
dryRun: false,
|
|
361
466
|
check: false,
|
|
362
467
|
rollback: false,
|
|
468
|
+
deploymentPersona: process.env.EXE_STACK_DEPLOYMENT_PERSONA === "askexe-control-plane" ? "askexe-control-plane" : "customer",
|
|
363
469
|
yes: false,
|
|
364
470
|
allowedBreakingChangeIds: []
|
|
365
471
|
};
|
|
@@ -390,6 +496,18 @@ function parseArgs(args) {
|
|
|
390
496
|
else if (arg === "--license-key") opts.licenseKey = next();
|
|
391
497
|
else if (arg.startsWith("--license-key=")) opts.licenseKey = arg.split("=").slice(1).join("=");
|
|
392
498
|
else if (arg === "--rollback") opts.rollback = true;
|
|
499
|
+
else if (arg === "--deployment-persona") {
|
|
500
|
+
const value = next();
|
|
501
|
+
if (value !== "customer" && value !== "askexe-control-plane") throw new Error(`Invalid --deployment-persona: ${value}`);
|
|
502
|
+
opts.deploymentPersona = value;
|
|
503
|
+
} else if (arg.startsWith("--deployment-persona=")) {
|
|
504
|
+
const value = arg.split("=").slice(1).join("=");
|
|
505
|
+
if (value !== "customer" && value !== "askexe-control-plane") throw new Error(`Invalid --deployment-persona: ${value}`);
|
|
506
|
+
opts.deploymentPersona = value;
|
|
507
|
+
} else if (arg === "--break-glass") opts.breakGlassReason = next();
|
|
508
|
+
else if (arg.startsWith("--break-glass=")) opts.breakGlassReason = arg.split("=").slice(1).join("=");
|
|
509
|
+
else if (arg === "--break-glass-audit-file") opts.breakGlassAuditFile = next();
|
|
510
|
+
else if (arg.startsWith("--break-glass-audit-file=")) opts.breakGlassAuditFile = arg.split("=").slice(1).join("=");
|
|
393
511
|
else if (arg === "--dry-run") opts.dryRun = true;
|
|
394
512
|
else if (arg === "--check") opts.check = true;
|
|
395
513
|
else if (arg === "--yes" || arg === "-y") opts.yes = true;
|
|
@@ -427,6 +545,9 @@ Options:
|
|
|
427
545
|
--device-id <id> Device ID to include in deploy audit
|
|
428
546
|
--license-key <key> License key to include in deploy audit
|
|
429
547
|
--rollback Restore latest backed-up .env and restart stack
|
|
548
|
+
--deployment-persona <customer|askexe-control-plane> Scope gate (default: customer)
|
|
549
|
+
--break-glass <reason> Emergency override for production deploy gate; writes audit file
|
|
550
|
+
--break-glass-audit-file <path> Audit file path for --break-glass
|
|
430
551
|
--allow-breaking <ids> Confirm breaking changes, comma-separated
|
|
431
552
|
-y, --yes Non-interactive confirmation
|
|
432
553
|
`);
|
|
@@ -466,6 +587,13 @@ async function main() {
|
|
|
466
587
|
const manifest = await loadStackManifest(opts.manifestRef, void 0, opts.manifestPublicKey, opts.manifestAuthToken);
|
|
467
588
|
const envRaw = readFileSync2(opts.envFile, "utf8");
|
|
468
589
|
const plan = createStackUpdatePlan(manifest, envRaw, opts.targetVersion);
|
|
590
|
+
assertDeploymentScopeAllowed(plan, opts.deploymentPersona);
|
|
591
|
+
const plannedEnvRaw = patchEnv(envRaw, Object.fromEntries(plan.changes.map((c) => [c.key, c.after])));
|
|
592
|
+
assertProductionDeployGate(plan, plannedEnvRaw, readFileSync2(opts.composeFile, "utf8"), {
|
|
593
|
+
breakGlassReason: opts.breakGlassReason,
|
|
594
|
+
breakGlassAuditFile: opts.breakGlassAuditFile,
|
|
595
|
+
envFile: opts.envFile
|
|
596
|
+
});
|
|
469
597
|
console.log(`Exe OS stack target: ${plan.targetVersion}`);
|
|
470
598
|
console.log(`Manifest: ${opts.manifestRef}`);
|
|
471
599
|
console.log(`Compose: ${opts.composeFile}`);
|
package/dist/gateway/index.js
CHANGED
|
@@ -3092,6 +3092,33 @@ async function ensureSchema() {
|
|
|
3092
3092
|
CREATE INDEX IF NOT EXISTS idx_chat_history_session
|
|
3093
3093
|
ON chat_history(session_id, id);
|
|
3094
3094
|
`);
|
|
3095
|
+
await client.executeMultiple(`
|
|
3096
|
+
CREATE TABLE IF NOT EXISTS session_events (
|
|
3097
|
+
id TEXT PRIMARY KEY,
|
|
3098
|
+
agent_id TEXT NOT NULL,
|
|
3099
|
+
agent_role TEXT NOT NULL,
|
|
3100
|
+
session_id TEXT NOT NULL,
|
|
3101
|
+
session_scope TEXT,
|
|
3102
|
+
project_name TEXT NOT NULL,
|
|
3103
|
+
event_index INTEGER NOT NULL,
|
|
3104
|
+
event_type TEXT NOT NULL,
|
|
3105
|
+
tool_name TEXT,
|
|
3106
|
+
tool_use_id TEXT,
|
|
3107
|
+
content TEXT NOT NULL,
|
|
3108
|
+
payload_json TEXT,
|
|
3109
|
+
has_error INTEGER NOT NULL DEFAULT 0,
|
|
3110
|
+
created_at TEXT NOT NULL
|
|
3111
|
+
);
|
|
3112
|
+
|
|
3113
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
|
|
3114
|
+
ON session_events(agent_id, created_at DESC);
|
|
3115
|
+
|
|
3116
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_session_index
|
|
3117
|
+
ON session_events(session_id, event_index);
|
|
3118
|
+
|
|
3119
|
+
CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
|
|
3120
|
+
ON session_events(session_scope, agent_id, created_at DESC);
|
|
3121
|
+
`);
|
|
3095
3122
|
await client.executeMultiple(`
|
|
3096
3123
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
3097
3124
|
id TEXT PRIMARY KEY,
|
|
@@ -4793,6 +4820,12 @@ var init_platform_procedures = __esm({
|
|
|
4793
4820
|
priority: "p0",
|
|
4794
4821
|
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."
|
|
4795
4822
|
},
|
|
4823
|
+
{
|
|
4824
|
+
title: "Code context first for repository orientation",
|
|
4825
|
+
domain: "workflow",
|
|
4826
|
+
priority: "p1",
|
|
4827
|
+
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."
|
|
4828
|
+
},
|
|
4796
4829
|
{
|
|
4797
4830
|
title: "Commit discipline \u2014 never leave verified work floating",
|
|
4798
4831
|
domain: "workflow",
|
|
@@ -6151,13 +6184,25 @@ var init_wiki_client = __esm({
|
|
|
6151
6184
|
|
|
6152
6185
|
// src/lib/code-chunker.ts
|
|
6153
6186
|
import ts from "typescript";
|
|
6187
|
+
function languageForFile(filePath) {
|
|
6188
|
+
const base = filePath.split(/[\\/]/).pop()?.toLowerCase() ?? "";
|
|
6189
|
+
if (["dockerfile", "makefile", "rakefile", "gemfile"].includes(base)) return base;
|
|
6190
|
+
const ext = base.includes(".") ? base.split(".").pop() : void 0;
|
|
6191
|
+
return ext ? LANGUAGE_BY_EXTENSION[ext] : void 0;
|
|
6192
|
+
}
|
|
6154
6193
|
function chunkSourceFile(source, fileName = "file.ts") {
|
|
6194
|
+
const language = languageForFile(fileName);
|
|
6195
|
+
if (language === "typescript" || language === "javascript") {
|
|
6196
|
+
return chunkTypeScriptLike(source, fileName);
|
|
6197
|
+
}
|
|
6198
|
+
return chunkGenericSource(source, fileName, language);
|
|
6199
|
+
}
|
|
6200
|
+
function chunkTypeScriptLike(source, fileName) {
|
|
6155
6201
|
const sourceFile = ts.createSourceFile(
|
|
6156
6202
|
fileName,
|
|
6157
6203
|
source,
|
|
6158
6204
|
ts.ScriptTarget.Latest,
|
|
6159
6205
|
true,
|
|
6160
|
-
// setParentNodes
|
|
6161
6206
|
fileName.endsWith(".tsx") || fileName.endsWith(".jsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS
|
|
6162
6207
|
);
|
|
6163
6208
|
const chunks = [];
|
|
@@ -6179,153 +6224,176 @@ function chunkSourceFile(source, fileName = "file.ts") {
|
|
|
6179
6224
|
if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) {
|
|
6180
6225
|
return node.name?.getText(sourceFile) ?? "(anonymous)";
|
|
6181
6226
|
}
|
|
6182
|
-
if (ts.isClassDeclaration(node))
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
if (ts.
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
if (ts.isTypeAliasDeclaration(node)) {
|
|
6189
|
-
return node.name.getText(sourceFile);
|
|
6190
|
-
}
|
|
6191
|
-
if (ts.isEnumDeclaration(node)) {
|
|
6192
|
-
return node.name.getText(sourceFile);
|
|
6193
|
-
}
|
|
6194
|
-
if (ts.isVariableStatement(node)) {
|
|
6195
|
-
const decls = node.declarationList.declarations;
|
|
6196
|
-
return decls.map((d) => d.name.getText(sourceFile)).join(", ");
|
|
6197
|
-
}
|
|
6198
|
-
if (ts.isExportAssignment(node)) {
|
|
6199
|
-
return "default export";
|
|
6200
|
-
}
|
|
6227
|
+
if (ts.isClassDeclaration(node)) return node.name?.getText(sourceFile) ?? "(anonymous class)";
|
|
6228
|
+
if (ts.isInterfaceDeclaration(node)) return node.name.getText(sourceFile);
|
|
6229
|
+
if (ts.isTypeAliasDeclaration(node)) return node.name.getText(sourceFile);
|
|
6230
|
+
if (ts.isEnumDeclaration(node)) return node.name.getText(sourceFile);
|
|
6231
|
+
if (ts.isVariableStatement(node)) return node.declarationList.declarations.map((d) => d.name.getText(sourceFile)).join(", ");
|
|
6232
|
+
if (ts.isExportAssignment(node)) return "default export";
|
|
6201
6233
|
return "(unknown)";
|
|
6202
6234
|
}
|
|
6203
6235
|
function visitTopLevel(node) {
|
|
6204
6236
|
if (ts.isImportDeclaration(node)) {
|
|
6205
|
-
importLines.push({
|
|
6206
|
-
start: getLineNumber(node.getStart(sourceFile)),
|
|
6207
|
-
end: getLineNumber(node.getEnd())
|
|
6208
|
-
});
|
|
6237
|
+
importLines.push({ start: getLineNumber(node.getStart(sourceFile)), end: getLineNumber(node.getEnd()) });
|
|
6209
6238
|
return;
|
|
6210
6239
|
}
|
|
6211
6240
|
if (ts.isFunctionDeclaration(node)) {
|
|
6212
|
-
chunks.push({
|
|
6213
|
-
kind: "function",
|
|
6214
|
-
name: getName(node),
|
|
6215
|
-
text: getNodeText(node),
|
|
6216
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6217
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6218
|
-
comment: getLeadingComment(node)
|
|
6219
|
-
});
|
|
6241
|
+
chunks.push({ kind: "function", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
|
|
6220
6242
|
return;
|
|
6221
6243
|
}
|
|
6222
6244
|
if (ts.isClassDeclaration(node)) {
|
|
6223
|
-
chunks.push({
|
|
6224
|
-
kind: "class",
|
|
6225
|
-
name: getName(node),
|
|
6226
|
-
text: getNodeText(node),
|
|
6227
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6228
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6229
|
-
comment: getLeadingComment(node)
|
|
6230
|
-
});
|
|
6245
|
+
chunks.push({ kind: "class", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
|
|
6231
6246
|
return;
|
|
6232
6247
|
}
|
|
6233
|
-
if (ts.isInterfaceDeclaration(node)) {
|
|
6234
|
-
chunks.push({
|
|
6235
|
-
kind: "type",
|
|
6236
|
-
name: getName(node),
|
|
6237
|
-
text: getNodeText(node),
|
|
6238
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6239
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6240
|
-
comment: getLeadingComment(node)
|
|
6241
|
-
});
|
|
6242
|
-
return;
|
|
6243
|
-
}
|
|
6244
|
-
if (ts.isTypeAliasDeclaration(node)) {
|
|
6245
|
-
chunks.push({
|
|
6246
|
-
kind: "type",
|
|
6247
|
-
name: getName(node),
|
|
6248
|
-
text: getNodeText(node),
|
|
6249
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6250
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6251
|
-
comment: getLeadingComment(node)
|
|
6252
|
-
});
|
|
6253
|
-
return;
|
|
6254
|
-
}
|
|
6255
|
-
if (ts.isEnumDeclaration(node)) {
|
|
6256
|
-
chunks.push({
|
|
6257
|
-
kind: "type",
|
|
6258
|
-
name: getName(node),
|
|
6259
|
-
text: getNodeText(node),
|
|
6260
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6261
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6262
|
-
comment: getLeadingComment(node)
|
|
6263
|
-
});
|
|
6248
|
+
if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node)) {
|
|
6249
|
+
chunks.push({ kind: "type", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
|
|
6264
6250
|
return;
|
|
6265
6251
|
}
|
|
6266
6252
|
if (ts.isVariableStatement(node)) {
|
|
6267
|
-
const
|
|
6268
|
-
|
|
6269
|
-
(d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer))
|
|
6270
|
-
);
|
|
6271
|
-
chunks.push({
|
|
6272
|
-
kind: isFnLike ? "function" : "variable",
|
|
6273
|
-
name: getName(node),
|
|
6274
|
-
text: getNodeText(node),
|
|
6275
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6276
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6277
|
-
comment: getLeadingComment(node)
|
|
6278
|
-
});
|
|
6253
|
+
const isFnLike = node.declarationList.declarations.some((d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer)));
|
|
6254
|
+
chunks.push({ kind: isFnLike ? "function" : "variable", name: getName(node), text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
|
|
6279
6255
|
return;
|
|
6280
6256
|
}
|
|
6281
6257
|
if (ts.isExportAssignment(node)) {
|
|
6282
|
-
chunks.push({
|
|
6283
|
-
kind: "export",
|
|
6284
|
-
name: "default export",
|
|
6285
|
-
text: getNodeText(node),
|
|
6286
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6287
|
-
endLine: getLineNumber(node.getEnd()),
|
|
6288
|
-
comment: getLeadingComment(node)
|
|
6289
|
-
});
|
|
6258
|
+
chunks.push({ kind: "export", name: "default export", text: getNodeText(node), startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()), comment: getLeadingComment(node) });
|
|
6290
6259
|
return;
|
|
6291
6260
|
}
|
|
6292
6261
|
if (ts.isExpressionStatement(node)) {
|
|
6293
6262
|
const text = getNodeText(node);
|
|
6294
|
-
if (text.length > 10) {
|
|
6295
|
-
chunks.push({
|
|
6296
|
-
kind: "other",
|
|
6297
|
-
name: text.slice(0, 40).replace(/\n/g, " "),
|
|
6298
|
-
text,
|
|
6299
|
-
startLine: getLineNumber(node.getStart(sourceFile)),
|
|
6300
|
-
endLine: getLineNumber(node.getEnd())
|
|
6301
|
-
});
|
|
6302
|
-
}
|
|
6303
|
-
return;
|
|
6263
|
+
if (text.length > 10) chunks.push({ kind: "other", name: text.slice(0, 40).replace(/\n/g, " "), text, startLine: getLineNumber(node.getStart(sourceFile)), endLine: getLineNumber(node.getEnd()) });
|
|
6304
6264
|
}
|
|
6305
6265
|
}
|
|
6306
6266
|
sourceFile.statements.forEach(visitTopLevel);
|
|
6307
6267
|
if (importLines.length > 0) {
|
|
6308
6268
|
const startLine = importLines[0].start;
|
|
6309
6269
|
const endLine = importLines[importLines.length - 1].end;
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6270
|
+
chunks.unshift({ kind: "import", name: `${importLines.length} imports`, text: lines.slice(startLine - 1, endLine).join("\n"), startLine, endLine });
|
|
6271
|
+
}
|
|
6272
|
+
chunks.sort((a, b) => a.startLine - b.startLine);
|
|
6273
|
+
return chunks.length > 0 ? chunks : chunkByWindows(source, 80);
|
|
6274
|
+
}
|
|
6275
|
+
function chunkGenericSource(source, _fileName, language) {
|
|
6276
|
+
const lines = source.split("\n");
|
|
6277
|
+
if (source.trim().length === 0) return [];
|
|
6278
|
+
if (language && TEXT_LIKE_LANGUAGES.has(language)) return chunkTextLike(lines, language);
|
|
6279
|
+
const chunks = [];
|
|
6280
|
+
const patterns = [
|
|
6281
|
+
{ kind: "function", regex: /^\s*(?:async\s+)?def\s+([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
|
|
6282
|
+
{ kind: "class", regex: /^\s*class\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
|
|
6283
|
+
{ kind: "function", regex: /^\s*(?:pub\s+)?fn\s+([A-Za-z_][\w]*)\s*[<(]/, name: (m) => m[1] },
|
|
6284
|
+
{ kind: "class", regex: /^\s*(?:pub\s+)?(?:struct|enum|trait)\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
|
|
6285
|
+
{ kind: "function", regex: /^\s*func\s+(?:\([^)]*\)\s*)?([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
|
|
6286
|
+
{ kind: "function", regex: /^\s*(?:public|private|protected|static|final|suspend|fun|override|open|internal|export|async|func|function|subroutine)\s+.*?([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
|
|
6287
|
+
{ kind: "function", regex: /^\s*function\s+([A-Za-z_][\w]*)\s*\(/, name: (m) => m[1] },
|
|
6288
|
+
{ kind: "type", regex: /^\s*(?:interface|type|enum|record|data\s+class|case\s+class|contract|library)\s+([A-Za-z_][\w]*)\b/, name: (m) => m[1] },
|
|
6289
|
+
{ kind: "section", regex: /^\s{0,3}#{1,6}\s+(.+)$/, name: (m) => m[1].trim() }
|
|
6290
|
+
];
|
|
6291
|
+
const starts = [];
|
|
6292
|
+
for (let i = 0; i < lines.length; i++) {
|
|
6293
|
+
const line = lines[i];
|
|
6294
|
+
for (const pattern of patterns) {
|
|
6295
|
+
const match = line.match(pattern.regex);
|
|
6296
|
+
if (match) {
|
|
6297
|
+
starts.push({ line: i + 1, kind: pattern.kind, name: pattern.name(match) });
|
|
6298
|
+
break;
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6301
|
+
}
|
|
6302
|
+
if (starts.length === 0) return chunkByWindows(source, 80);
|
|
6303
|
+
for (let i = 0; i < starts.length; i++) {
|
|
6304
|
+
const start = starts[i];
|
|
6305
|
+
const next = starts[i + 1]?.line ?? lines.length + 1;
|
|
6306
|
+
const endLine = Math.max(start.line, next - 1);
|
|
6307
|
+
chunks.push({
|
|
6308
|
+
kind: start.kind,
|
|
6309
|
+
name: start.name,
|
|
6310
|
+
text: lines.slice(start.line - 1, endLine).join("\n"),
|
|
6311
|
+
startLine: start.line,
|
|
6316
6312
|
endLine
|
|
6317
6313
|
});
|
|
6318
6314
|
}
|
|
6319
|
-
chunks
|
|
6315
|
+
return chunks;
|
|
6316
|
+
}
|
|
6317
|
+
function chunkTextLike(lines, language) {
|
|
6318
|
+
if (language === "markdown" || language === "mdx") {
|
|
6319
|
+
const starts = lines.map((line, i) => ({ line, i })).filter(({ line }) => /^\s{0,3}#{1,6}\s+/.test(line));
|
|
6320
|
+
if (starts.length > 0) {
|
|
6321
|
+
return starts.map((start, idx) => {
|
|
6322
|
+
const end = starts[idx + 1]?.i ?? lines.length;
|
|
6323
|
+
const title = start.line.replace(/^\s{0,3}#{1,6}\s+/, "").trim();
|
|
6324
|
+
return { kind: "section", name: title, text: lines.slice(start.i, end).join("\n"), startLine: start.i + 1, endLine: end };
|
|
6325
|
+
});
|
|
6326
|
+
}
|
|
6327
|
+
}
|
|
6328
|
+
return chunkByWindows(lines.join("\n"), 80);
|
|
6329
|
+
}
|
|
6330
|
+
function chunkByWindows(source, windowLines) {
|
|
6331
|
+
const lines = source.split("\n");
|
|
6332
|
+
const chunks = [];
|
|
6333
|
+
for (let i = 0; i < lines.length; i += windowLines) {
|
|
6334
|
+
const end = Math.min(lines.length, i + windowLines);
|
|
6335
|
+
const text = lines.slice(i, end).join("\n");
|
|
6336
|
+
if (text.trim()) chunks.push({ kind: "other", name: `lines ${i + 1}-${end}`, text, startLine: i + 1, endLine: end });
|
|
6337
|
+
}
|
|
6320
6338
|
return chunks;
|
|
6321
6339
|
}
|
|
6322
6340
|
function isChunkable(filePath) {
|
|
6323
|
-
|
|
6324
|
-
return ext === "ts" || ext === "tsx" || ext === "js" || ext === "jsx";
|
|
6341
|
+
return Boolean(languageForFile(filePath));
|
|
6325
6342
|
}
|
|
6343
|
+
var LANGUAGE_BY_EXTENSION, TEXT_LIKE_LANGUAGES;
|
|
6326
6344
|
var init_code_chunker = __esm({
|
|
6327
6345
|
"src/lib/code-chunker.ts"() {
|
|
6328
6346
|
"use strict";
|
|
6347
|
+
LANGUAGE_BY_EXTENSION = {
|
|
6348
|
+
c: "c",
|
|
6349
|
+
cc: "cpp",
|
|
6350
|
+
cpp: "cpp",
|
|
6351
|
+
cxx: "cpp",
|
|
6352
|
+
h: "c",
|
|
6353
|
+
hh: "cpp",
|
|
6354
|
+
hpp: "cpp",
|
|
6355
|
+
cs: "csharp",
|
|
6356
|
+
css: "css",
|
|
6357
|
+
scss: "scss",
|
|
6358
|
+
f: "fortran",
|
|
6359
|
+
f90: "fortran",
|
|
6360
|
+
f95: "fortran",
|
|
6361
|
+
go: "go",
|
|
6362
|
+
html: "html",
|
|
6363
|
+
htm: "html",
|
|
6364
|
+
java: "java",
|
|
6365
|
+
js: "javascript",
|
|
6366
|
+
jsx: "javascript",
|
|
6367
|
+
json: "json",
|
|
6368
|
+
kt: "kotlin",
|
|
6369
|
+
kts: "kotlin",
|
|
6370
|
+
lua: "lua",
|
|
6371
|
+
md: "markdown",
|
|
6372
|
+
mdx: "mdx",
|
|
6373
|
+
pas: "pascal",
|
|
6374
|
+
php: "php",
|
|
6375
|
+
py: "python",
|
|
6376
|
+
r: "r",
|
|
6377
|
+
rb: "ruby",
|
|
6378
|
+
rs: "rust",
|
|
6379
|
+
scala: "scala",
|
|
6380
|
+
sc: "scala",
|
|
6381
|
+
sol: "solidity",
|
|
6382
|
+
sql: "sql",
|
|
6383
|
+
svelte: "svelte",
|
|
6384
|
+
swift: "swift",
|
|
6385
|
+
toml: "toml",
|
|
6386
|
+
ts: "typescript",
|
|
6387
|
+
tsx: "typescript",
|
|
6388
|
+
vue: "vue",
|
|
6389
|
+
xml: "xml",
|
|
6390
|
+
yaml: "yaml",
|
|
6391
|
+
yml: "yaml",
|
|
6392
|
+
sh: "shell",
|
|
6393
|
+
bash: "shell",
|
|
6394
|
+
zsh: "shell"
|
|
6395
|
+
};
|
|
6396
|
+
TEXT_LIKE_LANGUAGES = /* @__PURE__ */ new Set(["json", "markdown", "mdx", "toml", "yaml", "xml", "html", "css", "scss", "sql"]);
|
|
6329
6397
|
}
|
|
6330
6398
|
});
|
|
6331
6399
|
|