@mindstudio-ai/remy 0.1.268 → 0.1.270
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/README.md +10 -18
- package/dist/headless.js +166 -220
- package/dist/index.js +140 -181
- package/dist/prompt/compiled/auth.md +20 -415
- package/dist/prompt/compiled/design.md +4 -2
- package/dist/prompt/compiled/dev-and-deploy.md +1 -8
- package/dist/prompt/compiled/interfaces.md +9 -27
- package/dist/prompt/compiled/methods.md +3 -37
- package/dist/prompt/compiled/msfm.md +1 -16
- package/dist/prompt/compiled/platform.md +7 -17
- package/dist/prompt/skills/auth.md +443 -0
- package/dist/prompt/{compiled → skills}/files.md +6 -0
- package/dist/prompt/{compiled → skills}/scenarios.md +6 -0
- package/dist/prompt/{compiled → skills}/secrets.md +6 -0
- package/dist/prompt/skills/voiceInterfaces.md +30 -10
- package/dist/prompt/static/authoring.md +1 -1
- package/dist/prompt/static/coding.md +4 -2
- package/dist/prompt/static/intake.md +1 -4
- package/dist/prompt/static/spec-maintenance.md +41 -0
- package/dist/prompt/static/team.md +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -872,12 +872,44 @@ var init_presentPublishPlan = __esm({
|
|
|
872
872
|
}
|
|
873
873
|
});
|
|
874
874
|
|
|
875
|
+
// src/atomicWrite.ts
|
|
876
|
+
import fs6 from "fs";
|
|
877
|
+
import fsp from "fs/promises";
|
|
878
|
+
var writeFileAtomicSync, writeFileAtomic;
|
|
879
|
+
var init_atomicWrite = __esm({
|
|
880
|
+
"src/atomicWrite.ts"() {
|
|
881
|
+
"use strict";
|
|
882
|
+
writeFileAtomicSync = (file, data) => {
|
|
883
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
884
|
+
const fd2 = fs6.openSync(tmp, "w");
|
|
885
|
+
try {
|
|
886
|
+
fs6.writeSync(fd2, data);
|
|
887
|
+
fs6.fsyncSync(fd2);
|
|
888
|
+
} finally {
|
|
889
|
+
fs6.closeSync(fd2);
|
|
890
|
+
}
|
|
891
|
+
fs6.renameSync(tmp, file);
|
|
892
|
+
};
|
|
893
|
+
writeFileAtomic = async (file, data) => {
|
|
894
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
895
|
+
const handle = await fsp.open(tmp, "w");
|
|
896
|
+
try {
|
|
897
|
+
await handle.writeFile(data);
|
|
898
|
+
await handle.sync();
|
|
899
|
+
} finally {
|
|
900
|
+
await handle.close();
|
|
901
|
+
}
|
|
902
|
+
await fsp.rename(tmp, file);
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
|
|
875
907
|
// src/tools/spec/writePlan.ts
|
|
876
|
-
import fs6 from "fs/promises";
|
|
877
908
|
var PLAN_FILE, writePlanTool;
|
|
878
909
|
var init_writePlan = __esm({
|
|
879
910
|
"src/tools/spec/writePlan.ts"() {
|
|
880
911
|
"use strict";
|
|
912
|
+
init_atomicWrite();
|
|
881
913
|
PLAN_FILE = ".remy-plan.md";
|
|
882
914
|
writePlanTool = {
|
|
883
915
|
definition: {
|
|
@@ -901,7 +933,7 @@ status: pending
|
|
|
901
933
|
---
|
|
902
934
|
|
|
903
935
|
${content}`;
|
|
904
|
-
await
|
|
936
|
+
await writeFileAtomic(PLAN_FILE, file);
|
|
905
937
|
return "Plan written to .remy-plan.md. Waiting for user approval.";
|
|
906
938
|
}
|
|
907
939
|
};
|
|
@@ -914,6 +946,7 @@ var PLAN_FILE2, updatePlanStatusTool;
|
|
|
914
946
|
var init_updatePlanStatus = __esm({
|
|
915
947
|
"src/tools/spec/updatePlanStatus.ts"() {
|
|
916
948
|
"use strict";
|
|
949
|
+
init_atomicWrite();
|
|
917
950
|
PLAN_FILE2 = ".remy-plan.md";
|
|
918
951
|
updatePlanStatusTool = {
|
|
919
952
|
definition: {
|
|
@@ -943,13 +976,13 @@ var init_updatePlanStatus = __esm({
|
|
|
943
976
|
return "No plan file found.";
|
|
944
977
|
}
|
|
945
978
|
if (status === "rejected") {
|
|
946
|
-
await fs7.unlink(PLAN_FILE2)
|
|
979
|
+
await fs7.unlink(PLAN_FILE2).catch(() => {
|
|
980
|
+
});
|
|
947
981
|
return "Plan rejected and removed.";
|
|
948
982
|
}
|
|
949
|
-
await
|
|
983
|
+
await writeFileAtomic(
|
|
950
984
|
PLAN_FILE2,
|
|
951
|
-
content.replace(/^status:\s*\w+/m, `status: ${status}`)
|
|
952
|
-
"utf-8"
|
|
985
|
+
content.replace(/^status:\s*\w+/m, `status: ${status}`)
|
|
953
986
|
);
|
|
954
987
|
return "Plan approved. Proceeding with implementation.";
|
|
955
988
|
}
|
|
@@ -1988,7 +2021,11 @@ Write the summary of the conversation above, following your instructions.`;
|
|
|
1988
2021
|
messages: [{ role: "user", content: userContent }],
|
|
1989
2022
|
// Always empty. With a toolset available the model picks `tool_use` over
|
|
1990
2023
|
// producing a summary, leaving summaryText empty.
|
|
1991
|
-
tools: []
|
|
2024
|
+
tools: [],
|
|
2025
|
+
// Each summary call carries a unique 100-200KB chunk that is never
|
|
2026
|
+
// re-read (parallel siblings can't read each other's in-flight writes
|
|
2027
|
+
// either) — a cache write here is pure waste.
|
|
2028
|
+
cachePolicy: "oneshot"
|
|
1992
2029
|
})) {
|
|
1993
2030
|
if (event.type === "text") {
|
|
1994
2031
|
summaryText += event.text;
|
|
@@ -2389,11 +2426,6 @@ var init_toolResultCap = __esm({
|
|
|
2389
2426
|
// src/session.ts
|
|
2390
2427
|
import fs10 from "fs";
|
|
2391
2428
|
import path4 from "path";
|
|
2392
|
-
function writeFileAtomicSync(file, data) {
|
|
2393
|
-
const tmp = `${file}.tmp`;
|
|
2394
|
-
fs10.writeFileSync(tmp, data, "utf-8");
|
|
2395
|
-
fs10.renameSync(tmp, file);
|
|
2396
|
-
}
|
|
2397
2429
|
function loadSession(state) {
|
|
2398
2430
|
pruneArchives();
|
|
2399
2431
|
try {
|
|
@@ -2411,6 +2443,12 @@ function loadSession(state) {
|
|
|
2411
2443
|
return true;
|
|
2412
2444
|
}
|
|
2413
2445
|
} catch {
|
|
2446
|
+
try {
|
|
2447
|
+
const quarantine = `${SESSION_FILE}.corrupt-${Date.now()}`;
|
|
2448
|
+
fs10.renameSync(SESSION_FILE, quarantine);
|
|
2449
|
+
log3.warn(`Session file unreadable \u2014 quarantined to ${quarantine}`);
|
|
2450
|
+
} catch {
|
|
2451
|
+
}
|
|
2414
2452
|
}
|
|
2415
2453
|
return false;
|
|
2416
2454
|
}
|
|
@@ -2716,6 +2754,7 @@ var log3, SESSION_FILE, ARCHIVE_DIR, ROTATE_THRESHOLD_BYTES, RETAIN_TAIL_BYTES,
|
|
|
2716
2754
|
var init_session = __esm({
|
|
2717
2755
|
"src/session.ts"() {
|
|
2718
2756
|
"use strict";
|
|
2757
|
+
init_atomicWrite();
|
|
2719
2758
|
init_logger();
|
|
2720
2759
|
init_compaction();
|
|
2721
2760
|
init_cleanMessages();
|
|
@@ -4140,7 +4179,8 @@ var init_uploadImage = __esm({
|
|
|
4140
4179
|
".jpg": "image/jpeg",
|
|
4141
4180
|
".jpeg": "image/jpeg",
|
|
4142
4181
|
".gif": "image/gif",
|
|
4143
|
-
".webp": "image/webp"
|
|
4182
|
+
".webp": "image/webp",
|
|
4183
|
+
".svg": "image/svg+xml"
|
|
4144
4184
|
};
|
|
4145
4185
|
hosted = /* @__PURE__ */ new Map();
|
|
4146
4186
|
}
|
|
@@ -4215,7 +4255,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
4215
4255
|
let onLog;
|
|
4216
4256
|
let model;
|
|
4217
4257
|
let apiConfig;
|
|
4218
|
-
let
|
|
4258
|
+
let path14;
|
|
4219
4259
|
let fullPage = true;
|
|
4220
4260
|
let width;
|
|
4221
4261
|
let height;
|
|
@@ -4223,7 +4263,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
4223
4263
|
if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
|
|
4224
4264
|
prompt = promptOrOptions.prompt;
|
|
4225
4265
|
existingImage = promptOrOptions.image;
|
|
4226
|
-
|
|
4266
|
+
path14 = promptOrOptions.path;
|
|
4227
4267
|
if (promptOrOptions.fullPage !== void 0) {
|
|
4228
4268
|
fullPage = promptOrOptions.fullPage;
|
|
4229
4269
|
}
|
|
@@ -4247,7 +4287,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
4247
4287
|
const ssResult = await sidecarRequest(
|
|
4248
4288
|
fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
|
|
4249
4289
|
{
|
|
4250
|
-
...
|
|
4290
|
+
...path14 ? { path: path14 } : {},
|
|
4251
4291
|
...width != null ? { width } : {},
|
|
4252
4292
|
...height != null ? { height } : {},
|
|
4253
4293
|
...format ? { format } : {}
|
|
@@ -4532,7 +4572,8 @@ async function runSubAgent(config) {
|
|
|
4532
4572
|
background,
|
|
4533
4573
|
acquireLock,
|
|
4534
4574
|
onBackgroundComplete,
|
|
4535
|
-
captureArtifacts
|
|
4575
|
+
captureArtifacts,
|
|
4576
|
+
cachePolicy = "run"
|
|
4536
4577
|
} = config;
|
|
4537
4578
|
const artifacts = {};
|
|
4538
4579
|
const bgAbort = background ? new AbortController() : null;
|
|
@@ -4627,6 +4668,7 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
|
|
|
4627
4668
|
system: fullSystem,
|
|
4628
4669
|
messages: cleanMessagesForApi(messages),
|
|
4629
4670
|
tools: tools2,
|
|
4671
|
+
cachePolicy,
|
|
4630
4672
|
signal
|
|
4631
4673
|
},
|
|
4632
4674
|
{
|
|
@@ -6433,7 +6475,7 @@ function load() {
|
|
|
6433
6475
|
}
|
|
6434
6476
|
function save(indices) {
|
|
6435
6477
|
try {
|
|
6436
|
-
|
|
6478
|
+
writeFileAtomicSync(SAMPLE_FILE, JSON.stringify(indices));
|
|
6437
6479
|
} catch {
|
|
6438
6480
|
}
|
|
6439
6481
|
}
|
|
@@ -6475,6 +6517,7 @@ var SAMPLE_FILE, cached2;
|
|
|
6475
6517
|
var init_sampleCache = __esm({
|
|
6476
6518
|
"src/subagents/designExpert/data/sampleCache.ts"() {
|
|
6477
6519
|
"use strict";
|
|
6520
|
+
init_atomicWrite();
|
|
6478
6521
|
SAMPLE_FILE = ".remy-design-sample.json";
|
|
6479
6522
|
cached2 = null;
|
|
6480
6523
|
}
|
|
@@ -6725,6 +6768,8 @@ async function runDesignExpert(opts, context) {
|
|
|
6725
6768
|
}),
|
|
6726
6769
|
task: opts.task,
|
|
6727
6770
|
history: history.length > 0 ? history : void 0,
|
|
6771
|
+
// History-carrying thread re-sent across parent turns — 1h-TTL profile.
|
|
6772
|
+
cachePolicy: "conversation",
|
|
6728
6773
|
tools: opts.render ? DESIGN_EXPERT_RENDER_TOOLS : DESIGN_EXPERT_TOOLS,
|
|
6729
6774
|
externalTools: /* @__PURE__ */ new Set(),
|
|
6730
6775
|
executeTool: (name, input, toolCallId, onLog, sams) => {
|
|
@@ -7052,6 +7097,8 @@ var init_productVision = __esm({
|
|
|
7052
7097
|
system: getProductVisionPrompt(),
|
|
7053
7098
|
task: input.task,
|
|
7054
7099
|
history: history.length > 0 ? history : void 0,
|
|
7100
|
+
// History-carrying thread re-sent across parent turns — 1h-TTL profile.
|
|
7101
|
+
cachePolicy: "conversation",
|
|
7055
7102
|
tools: VISION_TOOLS,
|
|
7056
7103
|
externalTools: /* @__PURE__ */ new Set(),
|
|
7057
7104
|
executeTool: (name, input2, toolCallId, _onLog, sams) => {
|
|
@@ -7529,7 +7576,7 @@ var init_scrapeWebUrl2 = __esm({
|
|
|
7529
7576
|
function deriveContext(parent, toolCallId) {
|
|
7530
7577
|
return { ...parent, toolCallId };
|
|
7531
7578
|
}
|
|
7532
|
-
function getToolDefinitions(
|
|
7579
|
+
function getToolDefinitions() {
|
|
7533
7580
|
return ALL_TOOLS.map((t) => t.definition);
|
|
7534
7581
|
}
|
|
7535
7582
|
function getToolByName(name) {
|
|
@@ -8034,7 +8081,10 @@ async function extractBrand(apiConfig, model) {
|
|
|
8034
8081
|
subAgentId: "brandExtractor",
|
|
8035
8082
|
system: EXTRACT_PROMPT,
|
|
8036
8083
|
messages: [{ role: "user", content: corpus }],
|
|
8037
|
-
tools: []
|
|
8084
|
+
tools: [],
|
|
8085
|
+
// One call per extraction over a corpus that changes with every spec
|
|
8086
|
+
// edit — never re-read, so a cache write is pure waste.
|
|
8087
|
+
cachePolicy: "oneshot"
|
|
8038
8088
|
})) {
|
|
8039
8089
|
if (event.type === "text") {
|
|
8040
8090
|
responseText += event.text;
|
|
@@ -8214,11 +8264,9 @@ function pickFont(raw) {
|
|
|
8214
8264
|
return out;
|
|
8215
8265
|
}
|
|
8216
8266
|
function persistBrand(brand, inputHash) {
|
|
8217
|
-
|
|
8218
|
-
fs20.writeFileSync(tmp, JSON.stringify(brand, null, 2), "utf-8");
|
|
8219
|
-
fs20.renameSync(tmp, BRAND_FILE);
|
|
8267
|
+
writeFileAtomicSync(BRAND_FILE, JSON.stringify(brand, null, 2));
|
|
8220
8268
|
const cache = { inputHash, generatedAt: Date.now() };
|
|
8221
|
-
|
|
8269
|
+
writeFileAtomicSync(CACHE_FILE, JSON.stringify(cache, null, 2));
|
|
8222
8270
|
}
|
|
8223
8271
|
function readCache() {
|
|
8224
8272
|
try {
|
|
@@ -8238,6 +8286,7 @@ var init_brandExtraction = __esm({
|
|
|
8238
8286
|
"use strict";
|
|
8239
8287
|
init_api();
|
|
8240
8288
|
init_assets();
|
|
8289
|
+
init_atomicWrite();
|
|
8241
8290
|
init_logger();
|
|
8242
8291
|
init_usageLedger();
|
|
8243
8292
|
log11 = createLogger("brandExtraction");
|
|
@@ -8312,7 +8361,7 @@ async function runTurn(params) {
|
|
|
8312
8361
|
toolRegistry,
|
|
8313
8362
|
onBackgroundComplete
|
|
8314
8363
|
} = params;
|
|
8315
|
-
const tools2 = getToolDefinitions(
|
|
8364
|
+
const tools2 = getToolDefinitions();
|
|
8316
8365
|
const buildModelOverride = buildModel ? filterModelPicks({ parent: buildModel }).parent : void 0;
|
|
8317
8366
|
const baseline = resolveModel("parent", state.models, model);
|
|
8318
8367
|
const parentModel = buildModelOverride ?? baseline;
|
|
@@ -8520,6 +8569,9 @@ async function runTurn(params) {
|
|
|
8520
8569
|
system,
|
|
8521
8570
|
messages: cleanMessagesForApi(state.messages),
|
|
8522
8571
|
tools: tools2,
|
|
8572
|
+
// The parent is one long-lived conversation re-read across turns
|
|
8573
|
+
// with multi-minute gaps — the 1h-TTL profile.
|
|
8574
|
+
cachePolicy: "conversation",
|
|
8523
8575
|
signal
|
|
8524
8576
|
},
|
|
8525
8577
|
{
|
|
@@ -8977,86 +9029,30 @@ var init_agent = __esm({
|
|
|
8977
9029
|
|
|
8978
9030
|
// src/prompt/static/projectContext.ts
|
|
8979
9031
|
import fs21 from "fs";
|
|
8980
|
-
import path12 from "path";
|
|
8981
9032
|
function loadProjectRoot() {
|
|
8982
9033
|
return `
|
|
8983
9034
|
## Project Root
|
|
8984
9035
|
\`${PROJECT_ROOT}\`
|
|
8985
9036
|
|
|
8986
|
-
File paths are relative to this directory. Every tool operates here and bash commands run
|
|
8987
|
-
}
|
|
8988
|
-
function loadProjectManifest() {
|
|
8989
|
-
try {
|
|
8990
|
-
const manifest = fs21.readFileSync("mindstudio.json", "utf-8");
|
|
8991
|
-
return `
|
|
8992
|
-
## Project Manifest (mindstudio.json)
|
|
8993
|
-
\`\`\`json
|
|
8994
|
-
${manifest}
|
|
8995
|
-
\`\`\``;
|
|
8996
|
-
} catch {
|
|
8997
|
-
return "";
|
|
8998
|
-
}
|
|
9037
|
+
File paths are relative to this directory. Every tool operates here and bash commands run in it.`;
|
|
8999
9038
|
}
|
|
9000
|
-
function
|
|
9039
|
+
function loadAppIdentity() {
|
|
9001
9040
|
try {
|
|
9002
|
-
const
|
|
9003
|
-
|
|
9041
|
+
const manifest = JSON.parse(fs21.readFileSync("mindstudio.json", "utf-8"));
|
|
9042
|
+
const name = typeof manifest.name === "string" ? manifest.name.trim() : "";
|
|
9043
|
+
if (!name) {
|
|
9004
9044
|
return "";
|
|
9005
9045
|
}
|
|
9006
|
-
const
|
|
9007
|
-
for (const filePath of files) {
|
|
9008
|
-
const { name, description, type } = parseFrontmatter4(filePath);
|
|
9009
|
-
let line = `- ${filePath}`;
|
|
9010
|
-
if (name) {
|
|
9011
|
-
line += ` \u2014 "${name}"`;
|
|
9012
|
-
}
|
|
9013
|
-
if (type) {
|
|
9014
|
-
line += ` (${type})`;
|
|
9015
|
-
}
|
|
9016
|
-
if (description) {
|
|
9017
|
-
line += ` \u2014 ${description}`;
|
|
9018
|
-
}
|
|
9019
|
-
entries.push(line);
|
|
9020
|
-
}
|
|
9046
|
+
const description = typeof manifest.description === "string" ? manifest.description.trim() : "";
|
|
9021
9047
|
return `
|
|
9022
|
-
##
|
|
9023
|
-
${
|
|
9048
|
+
## App
|
|
9049
|
+
"${name}"${description ? ` \u2014 ${description}` : ""}
|
|
9050
|
+
|
|
9051
|
+
Full manifest: \`mindstudio.json\` (read it when you need the app's structure, tables, methods, roles, auth settings, interfaces, and everything else).`;
|
|
9024
9052
|
} catch {
|
|
9025
9053
|
return "";
|
|
9026
9054
|
}
|
|
9027
9055
|
}
|
|
9028
|
-
function walkMdFiles3(dir) {
|
|
9029
|
-
const results = [];
|
|
9030
|
-
try {
|
|
9031
|
-
const entries = fs21.readdirSync(dir, { withFileTypes: true });
|
|
9032
|
-
for (const entry of entries) {
|
|
9033
|
-
const full = path12.join(dir, entry.name);
|
|
9034
|
-
if (entry.isDirectory()) {
|
|
9035
|
-
results.push(...walkMdFiles3(full));
|
|
9036
|
-
} else if (entry.name.endsWith(".md")) {
|
|
9037
|
-
results.push(full);
|
|
9038
|
-
}
|
|
9039
|
-
}
|
|
9040
|
-
} catch {
|
|
9041
|
-
}
|
|
9042
|
-
return results.sort();
|
|
9043
|
-
}
|
|
9044
|
-
function parseFrontmatter4(filePath) {
|
|
9045
|
-
try {
|
|
9046
|
-
const content = fs21.readFileSync(filePath, "utf-8");
|
|
9047
|
-
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
9048
|
-
if (!match) {
|
|
9049
|
-
return { name: "", description: "", type: "" };
|
|
9050
|
-
}
|
|
9051
|
-
const fm = match[1];
|
|
9052
|
-
const name = fm.match(/^name:\s*(.+)$/m)?.[1]?.trim() ?? "";
|
|
9053
|
-
const description = fm.match(/^description:\s*(.+)$/m)?.[1]?.trim() ?? "";
|
|
9054
|
-
const type = fm.match(/^type:\s*(.+)$/m)?.[1]?.trim() ?? "";
|
|
9055
|
-
return { name, description, type };
|
|
9056
|
-
} catch {
|
|
9057
|
-
return { name: "", description: "", type: "" };
|
|
9058
|
-
}
|
|
9059
|
-
}
|
|
9060
9056
|
function loadPlanStatus(onboardingState) {
|
|
9061
9057
|
try {
|
|
9062
9058
|
const content = fs21.readFileSync(".remy-plan.md", "utf-8");
|
|
@@ -9085,27 +9081,6 @@ The user has approved your implementation plan in .remy-plan.md. You may referen
|
|
|
9085
9081
|
return "";
|
|
9086
9082
|
}
|
|
9087
9083
|
}
|
|
9088
|
-
function loadProjectFileListing() {
|
|
9089
|
-
try {
|
|
9090
|
-
const entries = fs21.readdirSync(".", { withFileTypes: true });
|
|
9091
|
-
const listing = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
|
|
9092
|
-
if (a.isDirectory() && !b.isDirectory()) {
|
|
9093
|
-
return -1;
|
|
9094
|
-
}
|
|
9095
|
-
if (!a.isDirectory() && b.isDirectory()) {
|
|
9096
|
-
return 1;
|
|
9097
|
-
}
|
|
9098
|
-
return a.name.localeCompare(b.name);
|
|
9099
|
-
}).map((e) => e.isDirectory() ? `${e.name}/` : e.name).join("\n");
|
|
9100
|
-
return `
|
|
9101
|
-
## Project Files
|
|
9102
|
-
\`\`\`
|
|
9103
|
-
${listing}
|
|
9104
|
-
\`\`\``;
|
|
9105
|
-
} catch {
|
|
9106
|
-
return "";
|
|
9107
|
-
}
|
|
9108
|
-
}
|
|
9109
9084
|
var init_projectContext = __esm({
|
|
9110
9085
|
"src/prompt/static/projectContext.ts"() {
|
|
9111
9086
|
"use strict";
|
|
@@ -9121,13 +9096,7 @@ function resolveIncludes(template) {
|
|
|
9121
9096
|
);
|
|
9122
9097
|
return result.replace(/\n{3,}/g, "\n\n").trim();
|
|
9123
9098
|
}
|
|
9124
|
-
function buildSystemPrompt(onboardingState
|
|
9125
|
-
const projectContext = [
|
|
9126
|
-
loadProjectRoot(),
|
|
9127
|
-
loadProjectManifest(),
|
|
9128
|
-
loadSpecFileMetadata(),
|
|
9129
|
-
loadProjectFileListing()
|
|
9130
|
-
].filter(Boolean).join("\n");
|
|
9099
|
+
function buildSystemPrompt(onboardingState) {
|
|
9131
9100
|
const now = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
|
|
9132
9101
|
month: "long",
|
|
9133
9102
|
day: "numeric",
|
|
@@ -9136,8 +9105,6 @@ function buildSystemPrompt(onboardingState, viewContext) {
|
|
|
9136
9105
|
const template = `
|
|
9137
9106
|
{{static/identity.md}}
|
|
9138
9107
|
|
|
9139
|
-
Current date: ${now}
|
|
9140
|
-
|
|
9141
9108
|
<platform_docs>
|
|
9142
9109
|
<platform>
|
|
9143
9110
|
{{compiled/platform.md}}
|
|
@@ -9167,21 +9134,9 @@ Current date: ${now}
|
|
|
9167
9134
|
{{compiled/design.md}}
|
|
9168
9135
|
</design>
|
|
9169
9136
|
|
|
9170
|
-
<app_files>
|
|
9171
|
-
{{compiled/files.md}}
|
|
9172
|
-
</app_files>
|
|
9173
|
-
|
|
9174
9137
|
<interfaces>
|
|
9175
9138
|
{{compiled/interfaces.md}}
|
|
9176
9139
|
</interfaces>
|
|
9177
|
-
|
|
9178
|
-
<scenarios>
|
|
9179
|
-
{{compiled/scenarios.md}}
|
|
9180
|
-
</scenarios>
|
|
9181
|
-
|
|
9182
|
-
<secrets>
|
|
9183
|
-
{{compiled/secrets.md}}
|
|
9184
|
-
</secrets>
|
|
9185
9140
|
</platform_docs>
|
|
9186
9141
|
|
|
9187
9142
|
${loadSkillsCatalog()}
|
|
@@ -9194,12 +9149,12 @@ ${loadSkillsCatalog()}
|
|
|
9194
9149
|
{{compiled/msfm.md}}
|
|
9195
9150
|
</mindstudio_flavored_markdown_spec_docs>
|
|
9196
9151
|
|
|
9197
|
-
|
|
9152
|
+
${onboardingState === "intake" ? `<intake_mode_instructions>
|
|
9198
9153
|
{{static/intake.md}}
|
|
9199
|
-
</intake_mode_instructions
|
|
9154
|
+
</intake_mode_instructions>` : ""}
|
|
9200
9155
|
|
|
9201
9156
|
<spec_authoring_instructions>
|
|
9202
|
-
{{static/authoring.md}}
|
|
9157
|
+
${onboardingState !== void 0 && onboardingState !== "onboardingFinished" ? "{{static/authoring.md}}" : "{{static/spec-maintenance.md}}"}
|
|
9203
9158
|
</spec_authoring_instructions>
|
|
9204
9159
|
|
|
9205
9160
|
<team>
|
|
@@ -9217,11 +9172,11 @@ ${loadSkillsCatalog()}
|
|
|
9217
9172
|
<conversation_summaries>
|
|
9218
9173
|
Your conversation history may include <prior_conversation_summary> blocks in the user's messages. These are automated summaries of earlier messages that have been compacted to save context space. The user does not see this summary, they see the full conversation history in their UI. Treat the summary as ground truth for what happened before, but do not reference it directly to the user ("as mentioned in the summary..."). Just continue naturally as if you remember the prior work.
|
|
9219
9174
|
|
|
9220
|
-
|
|
9175
|
+
Tool results generally persist in the conversation until a compaction summarizes them. In rare cases very old tool results may be trimmed when the conversation nears the context limit. Either way, if you need something from an earlier tool call and can't see it anymore, just re-read the file or re-run the query.
|
|
9221
9176
|
</conversation_summaries>
|
|
9222
9177
|
|
|
9223
9178
|
<project_onboarding>
|
|
9224
|
-
New projects progress through
|
|
9179
|
+
New projects progress through four onboarding states. The user might skip this entirely and jump straight into working on the existing scaffold (which defaults to onboardingFinished), but ideally new projects move through each phase:
|
|
9225
9180
|
|
|
9226
9181
|
- **intake**: Gathering requirements. The project has scaffold code (a "hello world" starter) but it's not the user's app yet. Focus on understanding what they want to build, not on the existing code. Intake ends with a plan proposal via writePlan.
|
|
9227
9182
|
- **building**: The user approved the initial plan. The agent is writing the spec and building the app. This can take a while and involves heavy tool use (spec authoring, design expert consultation, code generation, verification, polishing).
|
|
@@ -9229,24 +9184,21 @@ New projects progress through three onboarding states. The user might skip this
|
|
|
9229
9184
|
- **onboardingFinished**: The project is built and ready. Full development mode with all tools available. From here on, keep spec and code in sync as changes are made.
|
|
9230
9185
|
</project_onboarding>
|
|
9231
9186
|
|
|
9187
|
+
${loadProjectRoot()}
|
|
9188
|
+
|
|
9189
|
+
${renderOrgContextBlock()}
|
|
9190
|
+
|
|
9232
9191
|
{{static/instructions.md}}
|
|
9233
9192
|
|
|
9234
9193
|
<!-- cache_breakpoint -->
|
|
9235
9194
|
|
|
9195
|
+
Current date: ${now}
|
|
9196
|
+
|
|
9236
9197
|
<current_project_onboarding_state>
|
|
9237
9198
|
${onboardingState ?? "onboardingFinished"}
|
|
9238
9199
|
</current_project_onboarding_state>
|
|
9239
9200
|
|
|
9240
|
-
|
|
9241
|
-
${projectContext}
|
|
9242
|
-
</project_context>
|
|
9243
|
-
|
|
9244
|
-
${renderOrgContextBlock()}
|
|
9245
|
-
|
|
9246
|
-
<view_context>
|
|
9247
|
-
The user is currently in ${viewContext?.mode ?? "code"} mode.
|
|
9248
|
-
${viewContext?.activeFile ? `Active file: ${viewContext.activeFile}` : ""}
|
|
9249
|
-
</view_context>
|
|
9201
|
+
${loadAppIdentity()}
|
|
9250
9202
|
|
|
9251
9203
|
${loadPlanStatus(onboardingState)}
|
|
9252
9204
|
`;
|
|
@@ -9264,7 +9216,7 @@ var init_prompt4 = __esm({
|
|
|
9264
9216
|
|
|
9265
9217
|
// src/config.ts
|
|
9266
9218
|
import fs22 from "fs";
|
|
9267
|
-
import
|
|
9219
|
+
import path12 from "path";
|
|
9268
9220
|
import os from "os";
|
|
9269
9221
|
function loadConfigFile() {
|
|
9270
9222
|
try {
|
|
@@ -9307,7 +9259,7 @@ var init_config = __esm({
|
|
|
9307
9259
|
"use strict";
|
|
9308
9260
|
init_logger();
|
|
9309
9261
|
log14 = createLogger("config");
|
|
9310
|
-
CONFIG_PATH =
|
|
9262
|
+
CONFIG_PATH = path12.join(
|
|
9311
9263
|
os.homedir(),
|
|
9312
9264
|
".mindstudio-local-tunnel",
|
|
9313
9265
|
"config.json"
|
|
@@ -9443,15 +9395,14 @@ var init_attachments = __esm({
|
|
|
9443
9395
|
});
|
|
9444
9396
|
|
|
9445
9397
|
// src/headless/planFile.ts
|
|
9446
|
-
import { readFileSync,
|
|
9398
|
+
import { readFileSync, unlinkSync } from "fs";
|
|
9447
9399
|
function applyPlanFileSideEffect(rawText) {
|
|
9448
9400
|
if (hasSentinel(rawText, "approvePlan") || hasSentinel(rawText, "approveInitialPlan")) {
|
|
9449
9401
|
try {
|
|
9450
9402
|
const plan = readFileSync(PLAN_FILE3, "utf-8");
|
|
9451
|
-
|
|
9403
|
+
writeFileAtomicSync(
|
|
9452
9404
|
PLAN_FILE3,
|
|
9453
|
-
plan.replace(/^status:\s*pending/m, "status: approved")
|
|
9454
|
-
"utf-8"
|
|
9405
|
+
plan.replace(/^status:\s*pending/m, "status: approved")
|
|
9455
9406
|
);
|
|
9456
9407
|
} catch {
|
|
9457
9408
|
}
|
|
@@ -9466,13 +9417,14 @@ var PLAN_FILE3;
|
|
|
9466
9417
|
var init_planFile = __esm({
|
|
9467
9418
|
"src/headless/planFile.ts"() {
|
|
9468
9419
|
"use strict";
|
|
9420
|
+
init_atomicWrite();
|
|
9469
9421
|
init_sentinel();
|
|
9470
9422
|
PLAN_FILE3 = ".remy-plan.md";
|
|
9471
9423
|
}
|
|
9472
9424
|
});
|
|
9473
9425
|
|
|
9474
9426
|
// src/headless/stats.ts
|
|
9475
|
-
import { readFileSync as readFileSync2
|
|
9427
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
9476
9428
|
function createSessionStats() {
|
|
9477
9429
|
return {
|
|
9478
9430
|
messageCount: 0,
|
|
@@ -9508,7 +9460,7 @@ function loadPassiveResults() {
|
|
|
9508
9460
|
}
|
|
9509
9461
|
function writeStats(stats, queue, passiveResults) {
|
|
9510
9462
|
try {
|
|
9511
|
-
|
|
9463
|
+
writeFileAtomicSync(
|
|
9512
9464
|
STATS_FILE,
|
|
9513
9465
|
JSON.stringify({
|
|
9514
9466
|
...stats,
|
|
@@ -9523,6 +9475,7 @@ var STATS_FILE;
|
|
|
9523
9475
|
var init_stats = __esm({
|
|
9524
9476
|
"src/headless/stats.ts"() {
|
|
9525
9477
|
"use strict";
|
|
9478
|
+
init_atomicWrite();
|
|
9526
9479
|
STATS_FILE = ".remy-stats.json";
|
|
9527
9480
|
}
|
|
9528
9481
|
});
|
|
@@ -9776,9 +9729,7 @@ var init_headless = __esm({
|
|
|
9776
9729
|
name: "compactConversation",
|
|
9777
9730
|
input: {},
|
|
9778
9731
|
startedAt: Date.now(),
|
|
9779
|
-
|
|
9780
|
-
uiOnly: true,
|
|
9781
|
-
result: "Compaction started in the background."
|
|
9732
|
+
uiOnly: true
|
|
9782
9733
|
}
|
|
9783
9734
|
]
|
|
9784
9735
|
});
|
|
@@ -9787,15 +9738,7 @@ var init_headless = __esm({
|
|
|
9787
9738
|
type: "tool_start",
|
|
9788
9739
|
id,
|
|
9789
9740
|
name: "compactConversation",
|
|
9790
|
-
input: {}
|
|
9791
|
-
background: true
|
|
9792
|
-
});
|
|
9793
|
-
this.onEvent({
|
|
9794
|
-
type: "tool_done",
|
|
9795
|
-
id,
|
|
9796
|
-
name: "compactConversation",
|
|
9797
|
-
result: "Compaction started in the background.",
|
|
9798
|
-
isError: false
|
|
9741
|
+
input: {}
|
|
9799
9742
|
});
|
|
9800
9743
|
}
|
|
9801
9744
|
} else {
|
|
@@ -9804,11 +9747,31 @@ var init_headless = __esm({
|
|
|
9804
9747
|
if (this.syntheticCompactionId) {
|
|
9805
9748
|
const id = this.syntheticCompactionId;
|
|
9806
9749
|
this.syntheticCompactionId = null;
|
|
9807
|
-
|
|
9750
|
+
const result = event.error ? `Error: ${event.error}` : formatSummariesResult(event.summaries ?? []);
|
|
9751
|
+
const isError = !!event.error;
|
|
9752
|
+
for (let i = this.state.messages.length - 1; i >= 0; i--) {
|
|
9753
|
+
const msg = this.state.messages[i];
|
|
9754
|
+
if (msg.role !== "assistant" || !Array.isArray(msg.content)) {
|
|
9755
|
+
continue;
|
|
9756
|
+
}
|
|
9757
|
+
const block = msg.content.find(
|
|
9758
|
+
(b) => b.type === "tool" && b.id === id
|
|
9759
|
+
);
|
|
9760
|
+
if (block && block.type === "tool") {
|
|
9761
|
+
block.result = result;
|
|
9762
|
+
block.isError = isError;
|
|
9763
|
+
block.completedAt = Date.now();
|
|
9764
|
+
saveSession(this.state);
|
|
9765
|
+
break;
|
|
9766
|
+
}
|
|
9767
|
+
}
|
|
9768
|
+
this.onEvent({
|
|
9769
|
+
type: "tool_done",
|
|
9808
9770
|
id,
|
|
9809
|
-
"compactConversation",
|
|
9810
|
-
|
|
9811
|
-
|
|
9771
|
+
name: "compactConversation",
|
|
9772
|
+
result,
|
|
9773
|
+
isError
|
|
9774
|
+
});
|
|
9812
9775
|
}
|
|
9813
9776
|
this.sessionStats.compactionInProgress = false;
|
|
9814
9777
|
if (!event.error) {
|
|
@@ -10269,10 +10232,7 @@ var init_headless = __esm({
|
|
|
10269
10232
|
const buildModel = hasSentinel(rawText, "approvePlan") ? parsed.buildModel : void 0;
|
|
10270
10233
|
const onboardingState = parsed.onboardingState ?? "onboardingFinished";
|
|
10271
10234
|
this.currentOnboardingState = onboardingState;
|
|
10272
|
-
const system = buildSystemPrompt(
|
|
10273
|
-
onboardingState,
|
|
10274
|
-
parsed.viewContext
|
|
10275
|
-
);
|
|
10235
|
+
const system = buildSystemPrompt(onboardingState);
|
|
10276
10236
|
if (resolved?.next && !fromChain) {
|
|
10277
10237
|
for (const step of getActionChain(resolved.next)) {
|
|
10278
10238
|
this.queue.push({
|
|
@@ -10349,13 +10309,12 @@ var init_headless = __esm({
|
|
|
10349
10309
|
}
|
|
10350
10310
|
const onboardingState = batch.find((b) => b.command.onboardingState !== void 0)?.command.onboardingState ?? this.currentOnboardingState ?? "onboardingFinished";
|
|
10351
10311
|
this.currentOnboardingState = onboardingState;
|
|
10352
|
-
const viewContext = [...batch].reverse().find((b) => b.command.viewContext !== void 0)?.command.viewContext;
|
|
10353
10312
|
await this.executeTurn({
|
|
10354
10313
|
entries,
|
|
10355
10314
|
requestId: primaryRid,
|
|
10356
10315
|
absorbedRids,
|
|
10357
10316
|
onboardingState,
|
|
10358
|
-
system: buildSystemPrompt(onboardingState
|
|
10317
|
+
system: buildSystemPrompt(onboardingState)
|
|
10359
10318
|
});
|
|
10360
10319
|
}
|
|
10361
10320
|
/**
|
|
@@ -10896,7 +10855,7 @@ var init_headless = __esm({
|
|
|
10896
10855
|
import { render } from "ink";
|
|
10897
10856
|
import os2 from "os";
|
|
10898
10857
|
import fs23 from "fs";
|
|
10899
|
-
import
|
|
10858
|
+
import path13 from "path";
|
|
10900
10859
|
|
|
10901
10860
|
// src/tui/App.tsx
|
|
10902
10861
|
import { useState as useState2, useCallback, useRef } from "react";
|
|
@@ -11050,7 +11009,7 @@ function App({ apiConfig, model }) {
|
|
|
11050
11009
|
return s;
|
|
11051
11010
|
});
|
|
11052
11011
|
const [sessionRestored] = useState2(() => agentState.messages.length > 0);
|
|
11053
|
-
const [system] = useState2(() => buildSystemPrompt());
|
|
11012
|
+
const [system] = useState2(() => buildSystemPrompt("onboardingFinished"));
|
|
11054
11013
|
useInput((input, key) => {
|
|
11055
11014
|
if (key.escape && isRunning && abortRef.current) {
|
|
11056
11015
|
abortRef.current.abort();
|
|
@@ -11222,7 +11181,7 @@ var startupLog = createLogger("startup");
|
|
|
11222
11181
|
function printDebugInfo(config) {
|
|
11223
11182
|
const pkg = JSON.parse(
|
|
11224
11183
|
fs23.readFileSync(
|
|
11225
|
-
|
|
11184
|
+
path13.join(import.meta.dirname, "..", "package.json"),
|
|
11226
11185
|
"utf-8"
|
|
11227
11186
|
)
|
|
11228
11187
|
);
|