dayloom 0.1.0-beta.0
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 +1146 -0
- package/dist/cli/daily.js +41 -0
- package/dist/cli/index.js +33 -0
- package/dist/cli/init.js +40 -0
- package/dist/cli/next.js +60 -0
- package/dist/cli/play.js +39 -0
- package/dist/cli/revise.js +41 -0
- package/dist/cli/settle.js +45 -0
- package/dist/daily/apply-plan.js +25 -0
- package/dist/daily/constants.js +16 -0
- package/dist/daily/dialogue-loop.js +147 -0
- package/dist/daily/finalize.js +23 -0
- package/dist/daily/guard.js +54 -0
- package/dist/daily/index.js +27 -0
- package/dist/daily/intent-router.js +65 -0
- package/dist/daily/mcp-gateway.js +5 -0
- package/dist/daily/mcp-tools.js +8 -0
- package/dist/daily/parse-assistant.js +38 -0
- package/dist/daily/parse-payload.js +10 -0
- package/dist/daily/player-context.js +85 -0
- package/dist/daily/project-plan.js +15 -0
- package/dist/daily/promptpile-loop.js +41 -0
- package/dist/daily/prompts.js +11 -0
- package/dist/daily/read-user-input.js +6 -0
- package/dist/daily/session.js +119 -0
- package/dist/daily/types.js +2 -0
- package/dist/daily/validate-plan.js +46 -0
- package/dist/i18n/detect.js +23 -0
- package/dist/i18n/index.js +22 -0
- package/dist/i18n/messages.js +149 -0
- package/dist/index.js +27 -0
- package/dist/init/apply-payload.js +18 -0
- package/dist/init/archive-transcript.js +28 -0
- package/dist/init/checklist.js +74 -0
- package/dist/init/cleanup.js +12 -0
- package/dist/init/constants.js +21 -0
- package/dist/init/errors.js +11 -0
- package/dist/init/finalize.js +35 -0
- package/dist/init/guard.js +31 -0
- package/dist/init/index.js +59 -0
- package/dist/init/interview-loop.js +103 -0
- package/dist/init/parse-assistant.js +50 -0
- package/dist/init/project-payload.js +78 -0
- package/dist/init/promptpile-run.js +80 -0
- package/dist/init/prompts.js +16 -0
- package/dist/init/read-user-input.js +44 -0
- package/dist/init/scaffold.js +66 -0
- package/dist/init/session.js +98 -0
- package/dist/init/types.js +2 -0
- package/dist/next/index.js +79 -0
- package/dist/next/inspect.js +90 -0
- package/dist/play/ai.js +11 -0
- package/dist/play/event-loop.js +244 -0
- package/dist/play/guard.js +14 -0
- package/dist/play/index.js +21 -0
- package/dist/play/parse-assistant.js +39 -0
- package/dist/play/player-context.js +20 -0
- package/dist/play/prompts.js +9 -0
- package/dist/play/session.js +14 -0
- package/dist/play/state.js +117 -0
- package/dist/play/types.js +2 -0
- package/dist/play/validate.js +156 -0
- package/dist/revise/apply-payload.js +58 -0
- package/dist/revise/bin-resolve.js +38 -0
- package/dist/revise/constants.js +17 -0
- package/dist/revise/dialogue-loop.js +116 -0
- package/dist/revise/diff.js +24 -0
- package/dist/revise/file-hash.js +27 -0
- package/dist/revise/finalize.js +23 -0
- package/dist/revise/guard.js +17 -0
- package/dist/revise/index.js +24 -0
- package/dist/revise/mcp-gateway.js +74 -0
- package/dist/revise/mcp-tools.js +91 -0
- package/dist/revise/parse-assistant.js +41 -0
- package/dist/revise/parse-payload.js +22 -0
- package/dist/revise/process-run.js +77 -0
- package/dist/revise/project-payload.js +62 -0
- package/dist/revise/promptpile-loop.js +41 -0
- package/dist/revise/prompts.js +16 -0
- package/dist/revise/read-user-input.js +35 -0
- package/dist/revise/session.js +119 -0
- package/dist/revise/types.js +2 -0
- package/dist/revise/validate-payload.js +47 -0
- package/dist/settle/ai.js +23 -0
- package/dist/settle/apply.js +58 -0
- package/dist/settle/context.js +69 -0
- package/dist/settle/derive.js +56 -0
- package/dist/settle/guard.js +71 -0
- package/dist/settle/index.js +105 -0
- package/dist/settle/parse-assistant.js +14 -0
- package/dist/settle/parse-payload.js +19 -0
- package/dist/settle/project.js +58 -0
- package/dist/settle/session.js +45 -0
- package/dist/settle/types.js +2 -0
- package/dist/settle/validate.js +100 -0
- package/dist/shared/filtered-stream-output.js +41 -0
- package/dist/shared/promptpile-stream.js +59 -0
- package/dist/shared/run-promptpile-with-stream.js +34 -0
- package/dist/utils/loading.js +54 -0
- package/package.json +39 -0
- package/prompts/README.md +39 -0
- package/prompts/choice.system.md +0 -0
- package/prompts/daily-dialogue.system.md +37 -0
- package/prompts/daily-finalize-plan.system.md +34 -0
- package/prompts/daily-intent-router.system.md +34 -0
- package/prompts/day-planner.system.md +0 -0
- package/prompts/day-summarizer.system.md +0 -0
- package/prompts/dialogue.system.md +0 -0
- package/prompts/diary-writer.system.md +0 -0
- package/prompts/event-runner.system.md +0 -0
- package/prompts/init-finalize.system.md +59 -0
- package/prompts/init-interviewer.system.md +37 -0
- package/prompts/memory-updater.system.md +0 -0
- package/prompts/next-day-seeder.system.md +0 -0
- package/prompts/play-event-dialogue.system.md +20 -0
- package/prompts/play-event-generator.system.md +19 -0
- package/prompts/play-event-resolver.system.md +26 -0
- package/prompts/play-replanner.system.md +21 -0
- package/prompts/revise-dialogue.system.md +22 -0
- package/prompts/revise-finalize.system.md +40 -0
- package/prompts/settle.system.md +28 -0
- package/prompts/spec.md +320 -0
- package/prompts/state-resolver.system.md +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.projectPayload = projectPayload;
|
|
4
|
+
function projectPayload(payload) {
|
|
5
|
+
const files = [
|
|
6
|
+
{
|
|
7
|
+
relativePath: 'manifest.yaml',
|
|
8
|
+
content: [
|
|
9
|
+
`id: ${payload.manifest.id}`,
|
|
10
|
+
`protocol_version: "0.0.0"`,
|
|
11
|
+
`created_at: ${new Date().toISOString()}`,
|
|
12
|
+
`title: ${yamlString(payload.manifest.title)}`,
|
|
13
|
+
'',
|
|
14
|
+
].join('\n'),
|
|
15
|
+
},
|
|
16
|
+
{ relativePath: 'canon/premise.md', content: payload.canon['premise.md'] },
|
|
17
|
+
{ relativePath: 'canon/rules.md', content: payload.canon['rules.md'] },
|
|
18
|
+
{ relativePath: 'canon/style.md', content: payload.canon['style.md'] },
|
|
19
|
+
{ relativePath: 'canon/user_role.md', content: payload.canon['user_role.md'] },
|
|
20
|
+
{ relativePath: 'state/world.yaml', content: payload.state['world.yaml'] },
|
|
21
|
+
{
|
|
22
|
+
relativePath: 'characters/index.yaml',
|
|
23
|
+
content: yamlIdList('characters', payload.characters.map(char => char.id)),
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
if (payload.state['calendar.yaml']) {
|
|
27
|
+
files.push({
|
|
28
|
+
relativePath: 'state/calendar.yaml',
|
|
29
|
+
content: payload.state['calendar.yaml'],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
for (const char of payload.characters) {
|
|
33
|
+
const dir = `characters/${char.id}`;
|
|
34
|
+
files.push({ relativePath: `${dir}/profile.md`, content: char.profileMd }, {
|
|
35
|
+
relativePath: `${dir}/relationships.md`,
|
|
36
|
+
content: char.relationshipsMd ?? '# Relationships\n\n',
|
|
37
|
+
}, {
|
|
38
|
+
relativePath: `${dir}/meta.yaml`,
|
|
39
|
+
content: entityMetaYaml(char.id, 'character', char.meta),
|
|
40
|
+
}, { relativePath: `${dir}/memory.md`, content: '' }, { relativePath: `${dir}/timeline.md`, content: '' });
|
|
41
|
+
}
|
|
42
|
+
if (payload.scenes?.length) {
|
|
43
|
+
files.push({
|
|
44
|
+
relativePath: 'scenes/index.yaml',
|
|
45
|
+
content: yamlIdList('scenes', payload.scenes.map(scene => scene.id)),
|
|
46
|
+
});
|
|
47
|
+
for (const scene of payload.scenes) {
|
|
48
|
+
const dir = `scenes/${scene.id}`;
|
|
49
|
+
files.push({ relativePath: `${dir}/profile.md`, content: scene.profileMd }, {
|
|
50
|
+
relativePath: `${dir}/meta.yaml`,
|
|
51
|
+
content: entityMetaYaml(scene.id, 'scene', scene.meta),
|
|
52
|
+
}, { relativePath: `${dir}/memory.md`, content: '' }, { relativePath: `${dir}/triggers.yaml`, content: 'triggers: []\n' }, { relativePath: `${dir}/timeline.md`, content: '' });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return files;
|
|
56
|
+
}
|
|
57
|
+
function yamlIdList(key, ids) {
|
|
58
|
+
return `${key}:\n${ids.map(id => ` - ${yamlString(id)}`).join('\n')}\n`;
|
|
59
|
+
}
|
|
60
|
+
function entityMetaYaml(id, type, meta) {
|
|
61
|
+
const tags = meta?.tags ?? [];
|
|
62
|
+
return [
|
|
63
|
+
`id: ${yamlScalar(id)}`,
|
|
64
|
+
`type: ${type}`,
|
|
65
|
+
`status: ${yamlScalar(meta?.status ?? 'active')}`,
|
|
66
|
+
tags.length ? `tags:\n${tags.map(tag => ` - ${yamlScalar(tag)}`).join('\n')}` : 'tags: []',
|
|
67
|
+
'',
|
|
68
|
+
].join('\n');
|
|
69
|
+
}
|
|
70
|
+
function yamlString(value) {
|
|
71
|
+
if (/[:#\n'"]/.test(value)) {
|
|
72
|
+
return JSON.stringify(value);
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
function yamlScalar(value) {
|
|
77
|
+
return JSON.stringify(value);
|
|
78
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getPromptpileSpawnConfig = getPromptpileSpawnConfig;
|
|
7
|
+
exports.runPromptpile = runPromptpile;
|
|
8
|
+
exports.assertPromptpileOk = assertPromptpileOk;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const promptpile_stream_1 = require("../shared/promptpile-stream");
|
|
12
|
+
const process_run_1 = require("../revise/process-run");
|
|
13
|
+
const OUTPUT_PILE_FD = 3;
|
|
14
|
+
function tryResolveBundledPromptpileScript() {
|
|
15
|
+
try {
|
|
16
|
+
const pkgJson = require.resolve('promptpile/package.json');
|
|
17
|
+
const script = path_1.default.join(path_1.default.dirname(pkgJson), 'dist', 'index.js');
|
|
18
|
+
return fs_1.default.existsSync(script) ? script : null;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function getPromptpileSpawnConfig() {
|
|
25
|
+
const bin = process.env.PROMPTPILE_BIN?.trim();
|
|
26
|
+
if (bin) {
|
|
27
|
+
return { command: bin, argvPrefix: [], displayName: bin };
|
|
28
|
+
}
|
|
29
|
+
const bundled = tryResolveBundledPromptpileScript();
|
|
30
|
+
if (bundled) {
|
|
31
|
+
return {
|
|
32
|
+
command: process.execPath,
|
|
33
|
+
argvPrefix: [bundled],
|
|
34
|
+
displayName: 'node "' + bundled + '"',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { command: 'promptpile', argvPrefix: [], displayName: 'promptpile' };
|
|
38
|
+
}
|
|
39
|
+
async function runPromptpile(session, cliArgs, options = {}) {
|
|
40
|
+
const spawnConfig = getPromptpileSpawnConfig();
|
|
41
|
+
const consumer = (0, promptpile_stream_1.createPromptpileStreamConsumer)({
|
|
42
|
+
onDelta: text => options.onDelta?.(text),
|
|
43
|
+
onError: message => {
|
|
44
|
+
throw new Error('promptpile stream error: ' + message);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
const result = await (0, process_run_1.runProcess)(spawnConfig.command, [
|
|
48
|
+
...spawnConfig.argvPrefix,
|
|
49
|
+
...cliArgs,
|
|
50
|
+
'--quiet',
|
|
51
|
+
'--output-pile-fd',
|
|
52
|
+
String(OUTPUT_PILE_FD),
|
|
53
|
+
'--output-pile-format',
|
|
54
|
+
'json'
|
|
55
|
+
], {
|
|
56
|
+
cwd: session.root,
|
|
57
|
+
quiet: options.quiet ?? true,
|
|
58
|
+
outputPile: {
|
|
59
|
+
fd: OUTPUT_PILE_FD,
|
|
60
|
+
onData: chunk => consumer.push(chunk)
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
try {
|
|
64
|
+
consumer.flush();
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
return { ...result, error: e instanceof Error ? e : new Error(String(e)) };
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
function assertPromptpileOk(result, context) {
|
|
72
|
+
if (result.error) {
|
|
73
|
+
throw new Error(context + ': failed to run promptpile (' + result.error.message + '). ' +
|
|
74
|
+
'Check ' + getPromptpileSpawnConfig().displayName + ' is available.');
|
|
75
|
+
}
|
|
76
|
+
if (result.status !== 0) {
|
|
77
|
+
const tail = result.stderr.trim().slice(-500);
|
|
78
|
+
throw new Error(context + ': promptpile exited with code ' + result.status + (tail ? ': ' + tail : ''));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadPrompt = loadPrompt;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const PROMPTS_DIR = path_1.default.resolve(__dirname, '../../prompts');
|
|
10
|
+
function loadPrompt(name) {
|
|
11
|
+
const filePath = path_1.default.join(PROMPTS_DIR, `${name}.system.md`);
|
|
12
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
13
|
+
throw new Error(`Prompt not found: ${filePath}`);
|
|
14
|
+
}
|
|
15
|
+
return fs_1.default.readFileSync(filePath, 'utf8');
|
|
16
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readUserInput = readUserInput;
|
|
7
|
+
const readline_1 = __importDefault(require("readline"));
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
async function readMultilineInput() {
|
|
10
|
+
process.stdout.write('\nEnter your reply. Finish with Ctrl+Z then Enter (Windows), or Ctrl+D (macOS/Linux).\n');
|
|
11
|
+
const rl = readline_1.default.createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout,
|
|
14
|
+
});
|
|
15
|
+
const lines = [];
|
|
16
|
+
for await (const line of rl) {
|
|
17
|
+
lines.push(line);
|
|
18
|
+
}
|
|
19
|
+
rl.close();
|
|
20
|
+
return lines.join('\n');
|
|
21
|
+
}
|
|
22
|
+
function askExitOnEmpty() {
|
|
23
|
+
const rl = readline_1.default.createInterface({
|
|
24
|
+
input: process.stdin,
|
|
25
|
+
output: process.stdout,
|
|
26
|
+
});
|
|
27
|
+
return new Promise(resolve => {
|
|
28
|
+
rl.question('Empty input. Exit? (Y/N): ', answer => {
|
|
29
|
+
rl.close();
|
|
30
|
+
resolve(/^y$/i.test(answer.trim()));
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function readUserInput() {
|
|
35
|
+
while (true) {
|
|
36
|
+
const text = (await readMultilineInput()).trim();
|
|
37
|
+
if (text) {
|
|
38
|
+
return text;
|
|
39
|
+
}
|
|
40
|
+
if (await askExitOnEmpty()) {
|
|
41
|
+
throw new errors_1.InitCancelledError();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.scaffoldEmptyWorld = scaffoldEmptyWorld;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
function writeFileIfMissing(filePath, content) {
|
|
11
|
+
if (fs_1.default.existsSync(filePath)) {
|
|
12
|
+
throw new Error(`Refusing to overwrite existing file: ${filePath}`);
|
|
13
|
+
}
|
|
14
|
+
fs_1.default.writeFileSync(filePath, content, 'utf8');
|
|
15
|
+
}
|
|
16
|
+
function ensureDir(dirPath) {
|
|
17
|
+
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
function scaffoldEmptyWorld(worldRoot, meta) {
|
|
20
|
+
const createdAt = meta.createdAt ?? new Date().toISOString();
|
|
21
|
+
ensureDir(worldRoot);
|
|
22
|
+
const files = [
|
|
23
|
+
[
|
|
24
|
+
'manifest.yaml',
|
|
25
|
+
[
|
|
26
|
+
`id: ${meta.id}`,
|
|
27
|
+
`protocol_version: "${constants_1.PROTOCOL_VERSION}"`,
|
|
28
|
+
`created_at: ${createdAt}`,
|
|
29
|
+
`title: ${meta.title}`,
|
|
30
|
+
'',
|
|
31
|
+
].join('\n'),
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
'current.yaml',
|
|
35
|
+
['day: day_0001', 'phase: idle', 'last_committed_day: null', ''].join('\n'),
|
|
36
|
+
],
|
|
37
|
+
['config.yaml', '# dayloom runtime config\n\n'],
|
|
38
|
+
['canon/premise.md', ''],
|
|
39
|
+
['canon/rules.md', ''],
|
|
40
|
+
['canon/style.md', ''],
|
|
41
|
+
['canon/user_role.md', ''],
|
|
42
|
+
['state/world.yaml', 'title: ""\n'],
|
|
43
|
+
['state/calendar.yaml', 'current_day: day_0001\n'],
|
|
44
|
+
['state/progress.yaml', 'arcs_active: []\n'],
|
|
45
|
+
['state/variables.yaml', 'variables: {}\n'],
|
|
46
|
+
['characters/index.yaml', 'characters: []\n'],
|
|
47
|
+
['scenes/index.yaml', 'scenes: []\n'],
|
|
48
|
+
['arcs/index.yaml', 'arcs: []\n'],
|
|
49
|
+
['memory/short_term.md', ''],
|
|
50
|
+
['memory/long_term.md', ''],
|
|
51
|
+
['memory/facts.yaml', 'facts: []\n'],
|
|
52
|
+
['memory/unresolved_threads.yaml', 'threads: []\n'],
|
|
53
|
+
['memory/important_events.yaml', 'events: []\n'],
|
|
54
|
+
['logs/state_changes.jsonl', ''],
|
|
55
|
+
['logs/generation_trace.md', ''],
|
|
56
|
+
['logs/errors.md', ''],
|
|
57
|
+
];
|
|
58
|
+
for (const [rel, content] of files) {
|
|
59
|
+
const filePath = path_1.default.join(worldRoot, rel);
|
|
60
|
+
ensureDir(path_1.default.dirname(filePath));
|
|
61
|
+
writeFileIfMissing(filePath, content);
|
|
62
|
+
}
|
|
63
|
+
ensureDir(path_1.default.join(worldRoot, 'days'));
|
|
64
|
+
ensureDir(path_1.default.join(worldRoot, 'exports', 'diaries'));
|
|
65
|
+
ensureDir(path_1.default.join(worldRoot, 'exports', 'summaries'));
|
|
66
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.scanMessageIndices = scanMessageIndices;
|
|
7
|
+
exports.appendUserMessage = appendUserMessage;
|
|
8
|
+
exports.getLatestAssistantText = getLatestAssistantText;
|
|
9
|
+
exports.buildTranscript = buildTranscript;
|
|
10
|
+
exports.createSession = createSession;
|
|
11
|
+
exports.writeOpeningAssistant = writeOpeningAssistant;
|
|
12
|
+
exports.createFinalizeSession = createFinalizeSession;
|
|
13
|
+
const fs_1 = __importDefault(require("fs"));
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const constants_1 = require("./constants");
|
|
17
|
+
const prompts_1 = require("./prompts");
|
|
18
|
+
const MESSAGE_PATTERN = /^\[(\d+)\](.+)\.md$/i;
|
|
19
|
+
function scanMessageIndices(messagesDir) {
|
|
20
|
+
if (!fs_1.default.existsSync(messagesDir)) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const indices = new Set();
|
|
24
|
+
for (const name of fs_1.default.readdirSync(messagesDir)) {
|
|
25
|
+
const m = name.match(MESSAGE_PATTERN);
|
|
26
|
+
if (m) {
|
|
27
|
+
indices.add(parseInt(m[1], 10));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return [...indices].sort((a, b) => a - b);
|
|
31
|
+
}
|
|
32
|
+
function appendUserMessage(messagesDir, content) {
|
|
33
|
+
const indices = scanMessageIndices(messagesDir);
|
|
34
|
+
const maxIdx = indices.length > 0 ? Math.max(...indices) : -1;
|
|
35
|
+
let nextIdx = maxIdx + 1;
|
|
36
|
+
let filePath = path_1.default.join(messagesDir, `[${nextIdx}]user.md`);
|
|
37
|
+
while (fs_1.default.existsSync(filePath)) {
|
|
38
|
+
nextIdx += 1;
|
|
39
|
+
filePath = path_1.default.join(messagesDir, `[${nextIdx}]user.md`);
|
|
40
|
+
}
|
|
41
|
+
fs_1.default.writeFileSync(filePath, content, 'utf8');
|
|
42
|
+
return filePath;
|
|
43
|
+
}
|
|
44
|
+
function getLatestAssistantText(messagesDir) {
|
|
45
|
+
const files = fs_1.default
|
|
46
|
+
.readdirSync(messagesDir)
|
|
47
|
+
.filter(n => /^\[\d+\]assistant\.md$/i.test(n))
|
|
48
|
+
.sort((a, b) => {
|
|
49
|
+
const ia = parseInt(a.match(/^\[(\d+)\]/)[1], 10);
|
|
50
|
+
const ib = parseInt(b.match(/^\[(\d+)\]/)[1], 10);
|
|
51
|
+
return ia - ib;
|
|
52
|
+
});
|
|
53
|
+
if (files.length === 0) {
|
|
54
|
+
throw new Error('No assistant message found in session');
|
|
55
|
+
}
|
|
56
|
+
const last = files[files.length - 1];
|
|
57
|
+
return fs_1.default.readFileSync(path_1.default.join(messagesDir, last), 'utf8');
|
|
58
|
+
}
|
|
59
|
+
function buildTranscript(messagesDir) {
|
|
60
|
+
const entries = fs_1.default
|
|
61
|
+
.readdirSync(messagesDir)
|
|
62
|
+
.map(name => {
|
|
63
|
+
const m = name.match(MESSAGE_PATTERN);
|
|
64
|
+
if (!m) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const idx = parseInt(m[1], 10);
|
|
68
|
+
const role = m[2];
|
|
69
|
+
const content = fs_1.default.readFileSync(path_1.default.join(messagesDir, name), 'utf8');
|
|
70
|
+
return { idx, role, content };
|
|
71
|
+
})
|
|
72
|
+
.filter((e) => e !== null)
|
|
73
|
+
.sort((a, b) => a.idx - b.idx || a.role.localeCompare(b.role));
|
|
74
|
+
return entries
|
|
75
|
+
.map(e => `## [${e.idx}] ${e.role}\n\n${e.content}`)
|
|
76
|
+
.join('\n\n');
|
|
77
|
+
}
|
|
78
|
+
function createSession() {
|
|
79
|
+
const root = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'dayloom-init-'));
|
|
80
|
+
const messagesDir = path_1.default.join(root, 'messages');
|
|
81
|
+
fs_1.default.mkdirSync(messagesDir, { recursive: true });
|
|
82
|
+
fs_1.default.writeFileSync(path_1.default.join(root, 'promptpile.toml'), constants_1.PROMPTPILE_TOML, 'utf8');
|
|
83
|
+
const systemPrompt = (0, prompts_1.loadPrompt)('init-interviewer');
|
|
84
|
+
fs_1.default.writeFileSync(path_1.default.join(messagesDir, '[0]system.md'), systemPrompt, 'utf8');
|
|
85
|
+
return { root, messagesDir, round: 0 };
|
|
86
|
+
}
|
|
87
|
+
function writeOpeningAssistant(messagesDir, opening) {
|
|
88
|
+
fs_1.default.writeFileSync(path_1.default.join(messagesDir, '[1]assistant.md'), opening, 'utf8');
|
|
89
|
+
}
|
|
90
|
+
function createFinalizeSession(transcript) {
|
|
91
|
+
const root = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'dayloom-finalize-'));
|
|
92
|
+
const messagesDir = path_1.default.join(root, 'messages');
|
|
93
|
+
fs_1.default.mkdirSync(messagesDir, { recursive: true });
|
|
94
|
+
fs_1.default.writeFileSync(path_1.default.join(root, 'promptpile.toml'), constants_1.PROMPTPILE_TOML, 'utf8');
|
|
95
|
+
fs_1.default.writeFileSync(path_1.default.join(messagesDir, '[0]system.md'), (0, prompts_1.loadPrompt)('init-finalize'), 'utf8');
|
|
96
|
+
fs_1.default.writeFileSync(path_1.default.join(messagesDir, '[1]user.md'), transcript, 'utf8');
|
|
97
|
+
return { root, messagesDir, round: 0 };
|
|
98
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.inspectNextState = exports.formatNextStatus = exports.describeNextAction = exports.InitCancelledError = void 0;
|
|
4
|
+
exports.runNext = runNext;
|
|
5
|
+
const daily_1 = require("../daily");
|
|
6
|
+
const i18n_1 = require("../i18n");
|
|
7
|
+
const init_1 = require("../init");
|
|
8
|
+
const errors_1 = require("../init/errors");
|
|
9
|
+
Object.defineProperty(exports, "InitCancelledError", { enumerable: true, get: function () { return errors_1.InitCancelledError; } });
|
|
10
|
+
const play_1 = require("../play");
|
|
11
|
+
const read_user_input_1 = require("../revise/read-user-input");
|
|
12
|
+
const settle_1 = require("../settle");
|
|
13
|
+
const inspect_1 = require("./inspect");
|
|
14
|
+
Object.defineProperty(exports, "describeNextAction", { enumerable: true, get: function () { return inspect_1.describeNextAction; } });
|
|
15
|
+
Object.defineProperty(exports, "formatNextStatus", { enumerable: true, get: function () { return inspect_1.formatNextStatus; } });
|
|
16
|
+
Object.defineProperty(exports, "inspectNextState", { enumerable: true, get: function () { return inspect_1.inspectNextState; } });
|
|
17
|
+
async function runNext(dir, options = {}) {
|
|
18
|
+
const t = options.t ?? (0, i18n_1.createTranslator)('en');
|
|
19
|
+
const state = (0, inspect_1.inspectNextState)(dir);
|
|
20
|
+
process.stdout.write(`${(0, inspect_1.formatNextStatus)(state, t)}\n`);
|
|
21
|
+
if (options.statusOnly)
|
|
22
|
+
return { state, action: state.action, executed: false };
|
|
23
|
+
process.stdout.write(`${(0, inspect_1.describeNextAction)(state, t)}\n`);
|
|
24
|
+
if (options.confirm && !(await (0, read_user_input_1.askYesNo)(t('next.proceed', { action: state.action })))) {
|
|
25
|
+
process.stdout.write(`${t('next.cancelled')}\n`);
|
|
26
|
+
return { state, action: state.action, executed: false };
|
|
27
|
+
}
|
|
28
|
+
switch (state.action) {
|
|
29
|
+
case 'init': {
|
|
30
|
+
const initOptions = {
|
|
31
|
+
id: options.id,
|
|
32
|
+
title: options.title,
|
|
33
|
+
maxRounds: options.maxRounds,
|
|
34
|
+
keepSessionOnError: options.keepSession,
|
|
35
|
+
};
|
|
36
|
+
const worldRoot = options.quick
|
|
37
|
+
? (0, init_1.initWorldQuick)(state.worldRoot, initOptions)
|
|
38
|
+
: await (0, init_1.initWorldInteractive)(state.worldRoot, initOptions);
|
|
39
|
+
process.stdout.write(`${t('next.initialized', { worldRoot })}\n`);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case 'daily':
|
|
43
|
+
await (0, daily_1.dailyInteractive)(state.worldRoot, commonAiOptions(options));
|
|
44
|
+
break;
|
|
45
|
+
case 'play':
|
|
46
|
+
await (0, play_1.playInteractive)(state.worldRoot, {
|
|
47
|
+
keepSession: options.keepSession,
|
|
48
|
+
maxToolRounds: options.maxToolRounds,
|
|
49
|
+
maxEventRounds: options.maxEventRounds,
|
|
50
|
+
mcpBaseUrl: options.mcpBaseUrl,
|
|
51
|
+
mcpToken: options.mcpToken,
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
case 'settle': {
|
|
55
|
+
const result = await (0, settle_1.settleWithAi)(state.worldRoot, commonAiOptions(options));
|
|
56
|
+
process.stdout.write(`${result.description}\n`);
|
|
57
|
+
if (result.applied)
|
|
58
|
+
process.stdout.write(`${t('cli.settle.settled', { day: result.day, nextDay: result.nextDay })}\n`);
|
|
59
|
+
else if (result.proposalPath) {
|
|
60
|
+
process.stdout.write(`${t('cli.settle.generatedProposal', { proposalPath: result.proposalPath })}\n${t('cli.settle.reviewProposal')}\n`);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
process.stdout.write(`${t('cli.common.dryRunOnly')}\n`);
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { state, action: state.action, executed: true };
|
|
69
|
+
}
|
|
70
|
+
function commonAiOptions(options) {
|
|
71
|
+
return {
|
|
72
|
+
dryRun: options.dryRun,
|
|
73
|
+
yes: options.yes,
|
|
74
|
+
keepSession: options.keepSession,
|
|
75
|
+
maxToolRounds: options.maxToolRounds,
|
|
76
|
+
mcpBaseUrl: options.mcpBaseUrl,
|
|
77
|
+
mcpToken: options.mcpToken,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.inspectNextState = inspectNextState;
|
|
7
|
+
exports.formatNextStatus = formatNextStatus;
|
|
8
|
+
exports.describeNextAction = describeNextAction;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const i18n_1 = require("../i18n");
|
|
12
|
+
function inspectNextState(dir) {
|
|
13
|
+
const worldRoot = path_1.default.resolve(dir);
|
|
14
|
+
const manifestPath = path_1.default.join(worldRoot, 'manifest.yaml');
|
|
15
|
+
if (!fs_1.default.existsSync(manifestPath)) {
|
|
16
|
+
return { kind: 'uninitialized', worldRoot, action: 'init' };
|
|
17
|
+
}
|
|
18
|
+
const currentPath = path_1.default.join(worldRoot, 'current.yaml');
|
|
19
|
+
if (!fs_1.default.existsSync(currentPath))
|
|
20
|
+
throw new Error('World save missing current.yaml');
|
|
21
|
+
const current = fs_1.default.readFileSync(currentPath, 'utf8');
|
|
22
|
+
const day = readYamlScalar(current, 'day', 'current.yaml');
|
|
23
|
+
const phase = readPhase(readYamlScalar(current, 'phase', 'current.yaml'));
|
|
24
|
+
const lastCommittedDay = readOptionalYamlScalar(current, 'last_committed_day');
|
|
25
|
+
return {
|
|
26
|
+
kind: 'initialized',
|
|
27
|
+
worldRoot,
|
|
28
|
+
day,
|
|
29
|
+
phase,
|
|
30
|
+
lastCommittedDay,
|
|
31
|
+
action: actionForPhase(phase),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function formatNextStatus(state, t = (0, i18n_1.createTranslator)('en')) {
|
|
35
|
+
const lines = [t('next.world', { worldRoot: state.worldRoot })];
|
|
36
|
+
if (state.kind === 'uninitialized') {
|
|
37
|
+
lines.push(t('next.currentUninitialized'));
|
|
38
|
+
lines.push(t('next.nextAction', { action: 'init' }));
|
|
39
|
+
lines.push(t('next.recommendedCommand'));
|
|
40
|
+
lines.push(` dayloom init -d ${state.worldRoot}`);
|
|
41
|
+
return lines.join('\n');
|
|
42
|
+
}
|
|
43
|
+
lines.push(t('next.currentPhase', { day: state.day, phase: state.phase }));
|
|
44
|
+
if (state.lastCommittedDay)
|
|
45
|
+
lines.push(t('next.lastCommittedDay', { lastCommittedDay: state.lastCommittedDay }));
|
|
46
|
+
lines.push(t('next.nextAction', { action: state.action }));
|
|
47
|
+
lines.push(t('next.recommendedCommand'));
|
|
48
|
+
lines.push(` dayloom ${state.action} -d ${state.worldRoot}`);
|
|
49
|
+
return lines.join('\n');
|
|
50
|
+
}
|
|
51
|
+
function describeNextAction(state, t = (0, i18n_1.createTranslator)('en')) {
|
|
52
|
+
switch (state.action) {
|
|
53
|
+
case 'init':
|
|
54
|
+
return t('next.actionInit');
|
|
55
|
+
case 'daily':
|
|
56
|
+
return t('next.actionDaily');
|
|
57
|
+
case 'play':
|
|
58
|
+
return state.kind === 'initialized' && state.phase === 'playing'
|
|
59
|
+
? t('next.actionPlayContinue')
|
|
60
|
+
: t('next.actionPlayStart');
|
|
61
|
+
case 'settle':
|
|
62
|
+
return t('next.actionSettle');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function actionForPhase(phase) {
|
|
66
|
+
switch (phase) {
|
|
67
|
+
case 'idle':
|
|
68
|
+
return 'daily';
|
|
69
|
+
case 'planned':
|
|
70
|
+
case 'playing':
|
|
71
|
+
return 'play';
|
|
72
|
+
case 'settling':
|
|
73
|
+
return 'settle';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function readPhase(value) {
|
|
77
|
+
if (value === 'idle' || value === 'planned' || value === 'playing' || value === 'settling')
|
|
78
|
+
return value;
|
|
79
|
+
throw new Error(`Unsupported current phase for next: ${value}`);
|
|
80
|
+
}
|
|
81
|
+
function readYamlScalar(text, key, label) {
|
|
82
|
+
const match = text.match(new RegExp(`^${key}:\\s*(\\S+)\\s*$`, 'm'));
|
|
83
|
+
if (!match)
|
|
84
|
+
throw new Error(`${label} missing ${key}`);
|
|
85
|
+
return match[1];
|
|
86
|
+
}
|
|
87
|
+
function readOptionalYamlScalar(text, key) {
|
|
88
|
+
const match = text.match(new RegExp(`^${key}:\\s*(\\S+)\\s*$`, 'm'));
|
|
89
|
+
return match?.[1];
|
|
90
|
+
}
|
package/dist/play/ai.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.callPlayAi = callPlayAi;
|
|
4
|
+
const promptpile_loop_1 = require("../daily/promptpile-loop");
|
|
5
|
+
const session_1 = require("./session");
|
|
6
|
+
async function callPlayAi(prompt, userContent, toolsFile, baseUrl, token, maxToolRounds, onDelta = () => undefined) { const session = (0, session_1.createPlayAiSession)(prompt, userContent, toolsFile); try {
|
|
7
|
+
return await (0, promptpile_loop_1.runPromptpileUntilText)(session, baseUrl, token, maxToolRounds, onDelta);
|
|
8
|
+
}
|
|
9
|
+
finally {
|
|
10
|
+
(0, session_1.cleanupPlayAiSession)(session);
|
|
11
|
+
} }
|