AI協調開発研究ドキュメントの完成と Phase 10.9-β 進捗
【AI協調開発研究】 - AI二重化モデルの学術論文draft完成(workshop_paper_draft.md) - 「隠れた危機」分析とbirthの原則哲学化 - TyEnv「唯一の真実」協調会話を保存・研究資料に統合 - papers管理構造の整備(wip/under-review/published分離) 【Phase 10.9-β HostCall進捗】 - JitConfigBox: relax_numeric フラグ追加(i64→f64コアーション制御) - HostcallRegistryBox: 署名検証・白黒リスト・コアーション対応 - JitHostcallRegistryBox: Nyash側レジストリ操作API - Lower統合: env直読 → jit::config::current() 参照に統一 - 数値緩和設定: NYASH_JIT_HOSTCALL_RELAX_NUMERIC/Config.set_flag 【検証サンプル拡充】 - math.sin/cos/abs/min/max 関数スタイル(examples/jit_math_function_style_*.nyash) - 境界ケース: 署名不一致・コアーション許可・mutating拒否サンプル - E2E実証: String.length→allow, Array.push→fallback, math関数の署名一致観測 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
184
tools/codex-tmux-driver/common-message-file.js
Normal file
184
tools/codex-tmux-driver/common-message-file.js
Normal file
@ -0,0 +1,184 @@
|
||||
// common-message-file.js
|
||||
// 共通テキストファイル経由の通信システム
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
class FileBasedMessenger extends EventEmitter {
|
||||
constructor(config = {}) {
|
||||
super();
|
||||
this.config = {
|
||||
messageFile: config.messageFile || './shared-messages.txt',
|
||||
lockFile: config.lockFile || './shared-messages.lock',
|
||||
pollInterval: config.pollInterval || 500,
|
||||
...config
|
||||
};
|
||||
|
||||
this.lastReadPosition = 0;
|
||||
this.isWatching = false;
|
||||
}
|
||||
|
||||
// メッセージを書き込む
|
||||
async sendMessage(from, to, message) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const entry = JSON.stringify({
|
||||
timestamp,
|
||||
from,
|
||||
to,
|
||||
message
|
||||
}) + '\n';
|
||||
|
||||
// ロックを取得
|
||||
await this.acquireLock();
|
||||
|
||||
try {
|
||||
// ファイルに追記
|
||||
fs.appendFileSync(this.config.messageFile, entry);
|
||||
console.log(`📤 Sent: ${from} → ${to}: ${message}`);
|
||||
} finally {
|
||||
// ロック解放
|
||||
this.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
// メッセージを監視
|
||||
startWatching(myName) {
|
||||
this.isWatching = true;
|
||||
console.log(`👁️ Watching messages for: ${myName}`);
|
||||
|
||||
// 初期位置を設定
|
||||
if (fs.existsSync(this.config.messageFile)) {
|
||||
const stats = fs.statSync(this.config.messageFile);
|
||||
this.lastReadPosition = stats.size;
|
||||
}
|
||||
|
||||
// 定期的にチェック
|
||||
const checkMessages = () => {
|
||||
if (!this.isWatching) return;
|
||||
|
||||
try {
|
||||
if (!fs.existsSync(this.config.messageFile)) {
|
||||
setTimeout(checkMessages, this.config.pollInterval);
|
||||
return;
|
||||
}
|
||||
|
||||
const stats = fs.statSync(this.config.messageFile);
|
||||
if (stats.size > this.lastReadPosition) {
|
||||
// 新しいメッセージがある
|
||||
const buffer = Buffer.alloc(stats.size - this.lastReadPosition);
|
||||
const fd = fs.openSync(this.config.messageFile, 'r');
|
||||
fs.readSync(fd, buffer, 0, buffer.length, this.lastReadPosition);
|
||||
fs.closeSync(fd);
|
||||
|
||||
const newLines = buffer.toString().trim().split('\n');
|
||||
|
||||
for (const line of newLines) {
|
||||
if (line) {
|
||||
try {
|
||||
const msg = JSON.parse(line);
|
||||
// 自分宛のメッセージ
|
||||
if (msg.to === myName || msg.to === '*') {
|
||||
this.emit('message', msg);
|
||||
console.log(`📨 Received: ${msg.from} → ${msg.to}: ${msg.message}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Parse error:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.lastReadPosition = stats.size;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Watch error:', err);
|
||||
}
|
||||
|
||||
setTimeout(checkMessages, this.config.pollInterval);
|
||||
};
|
||||
|
||||
checkMessages();
|
||||
}
|
||||
|
||||
// 監視停止
|
||||
stopWatching() {
|
||||
this.isWatching = false;
|
||||
console.log('🛑 Stopped watching');
|
||||
}
|
||||
|
||||
// 簡易ロック機構
|
||||
async acquireLock(maxWait = 5000) {
|
||||
const startTime = Date.now();
|
||||
|
||||
while (fs.existsSync(this.config.lockFile)) {
|
||||
if (Date.now() - startTime > maxWait) {
|
||||
throw new Error('Lock timeout');
|
||||
}
|
||||
await this.sleep(50);
|
||||
}
|
||||
|
||||
fs.writeFileSync(this.config.lockFile, process.pid.toString());
|
||||
}
|
||||
|
||||
releaseLock() {
|
||||
if (fs.existsSync(this.config.lockFile)) {
|
||||
fs.unlinkSync(this.config.lockFile);
|
||||
}
|
||||
}
|
||||
|
||||
sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
// メッセージ履歴をクリア
|
||||
clearMessages() {
|
||||
if (fs.existsSync(this.config.messageFile)) {
|
||||
fs.unlinkSync(this.config.messageFile);
|
||||
}
|
||||
console.log('🗑️ Message history cleared');
|
||||
}
|
||||
}
|
||||
|
||||
// CLIとして使用
|
||||
if (require.main === module) {
|
||||
const messenger = new FileBasedMessenger();
|
||||
const myName = process.argv[2];
|
||||
const command = process.argv[3];
|
||||
|
||||
if (!myName || !command) {
|
||||
console.log(`
|
||||
使い方:
|
||||
node common-message-file.js <名前> watch # メッセージを監視
|
||||
node common-message-file.js <名前> send <宛先> <内容> # メッセージ送信
|
||||
node common-message-file.js <名前> clear # 履歴クリア
|
||||
`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case 'watch':
|
||||
messenger.on('message', (msg) => {
|
||||
// 自動返信(デモ用)
|
||||
if (msg.message.includes('?')) {
|
||||
setTimeout(() => {
|
||||
messenger.sendMessage(myName, msg.from, 'はい、了解しました!');
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
messenger.startWatching(myName);
|
||||
console.log('Press Ctrl+C to stop...');
|
||||
break;
|
||||
|
||||
case 'send':
|
||||
const to = process.argv[4];
|
||||
const message = process.argv.slice(5).join(' ');
|
||||
messenger.sendMessage(myName, to, message);
|
||||
break;
|
||||
|
||||
case 'clear':
|
||||
messenger.clearMessages();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileBasedMessenger;
|
||||
Reference in New Issue
Block a user