replicas-engine 0.1.7 → 0.1.9

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.
@@ -1,4 +1,5 @@
1
1
  import { Codex, Thread } from '@openai/codex-sdk';
2
+ import { randomUUID } from 'crypto';
2
3
  import { findSessionFile, readJSONL } from '../utils/jsonl-reader.js';
3
4
  export class CodexManager {
4
5
  codex;
@@ -23,74 +24,133 @@ export class CodexManager {
23
24
  }
24
25
  }
25
26
  async sendMessage(message) {
27
+ console.log(`[CodexManager] sendMessage called with message length: ${message.length}`);
26
28
  if (!this.currentThread) {
27
29
  if (this.currentThreadId) {
28
- console.log(`Resuming thread ${this.currentThreadId}`);
30
+ console.log(`[CodexManager] Resuming existing thread: ${this.currentThreadId}`);
29
31
  this.currentThread = this.codex.resumeThread(this.currentThreadId, {
30
32
  workingDirectory: this.workingDirectory,
31
33
  skipGitRepoCheck: true,
32
34
  sandboxMode: 'danger-full-access',
33
35
  });
36
+ console.log(`[CodexManager] Thread resumed successfully`);
34
37
  }
35
38
  else {
36
- console.log('Starting new thread');
39
+ console.log('[CodexManager] No existing thread, starting new thread');
40
+ console.log(`[CodexManager] Working directory: ${this.workingDirectory}`);
37
41
  this.currentThread = this.codex.startThread({
38
42
  workingDirectory: this.workingDirectory,
39
43
  skipGitRepoCheck: true,
40
44
  sandboxMode: 'danger-full-access',
41
45
  });
46
+ if (this.currentThread.id) {
47
+ this.currentThreadId = this.currentThread.id;
48
+ console.log(`[CodexManager] New thread created with ID: ${this.currentThreadId}`);
49
+ }
50
+ else {
51
+ console.error('[CodexManager] ERROR: Thread created but no ID available');
52
+ }
53
+ // prime the thread with system instructions if thread is new
54
+ const workspaceName = process.env.WORKSPACE_NAME || 'workspace';
55
+ console.log(`[CodexManager] Workspace name from env: ${workspaceName}`);
56
+ const workspaceBranchSegment = workspaceName
57
+ .trim()
58
+ .toLowerCase()
59
+ .replace(/[^a-z0-9]+/g, '-')
60
+ .replace(/^-+|-+$/g, '') || 'workspace';
61
+ const uuid = randomUUID().slice(0, 8);
62
+ const branchName = `replicas/${workspaceBranchSegment}-${uuid}`;
63
+ console.log(`[CodexManager] Generated branch name: ${branchName}`);
64
+ const systemMessage = `<replicas_important_instructions>When completing solutions, push your changes to branch ${branchName} and to origin. Greet the user.</replicas_important_instructions>`;
65
+ console.log('[CodexManager] Starting thread priming with system instructions');
66
+ const primingStartTime = Date.now();
67
+ await this.currentThread.run(systemMessage);
68
+ const primingDuration = Date.now() - primingStartTime;
69
+ console.log(`[CodexManager] Thread priming completed in ${primingDuration}ms`);
42
70
  }
43
71
  }
44
- await this.currentThread.run(message);
45
- if (!this.currentThreadId && this.currentThread.id) {
46
- this.currentThreadId = this.currentThread.id;
47
- console.log(`Thread started: ${this.currentThreadId}`);
72
+ else {
73
+ console.log(`[CodexManager] Using existing thread object for thread ID: ${this.currentThreadId}`);
48
74
  }
75
+ console.log(`[CodexManager] Running user message on thread ${this.currentThreadId}`);
76
+ const messageStartTime = Date.now();
77
+ await this.currentThread.run(message);
78
+ const messageDuration = Date.now() - messageStartTime;
79
+ console.log(`[CodexManager] User message run completed in ${messageDuration}ms`);
49
80
  }
50
81
  async getHistory() {
82
+ console.log('[CodexManager] getHistory called');
51
83
  if (!this.currentThreadId) {
84
+ console.log('[CodexManager] No active thread ID, returning empty history');
52
85
  return {
53
86
  thread_id: null,
54
87
  events: [],
55
88
  };
56
89
  }
90
+ console.log(`[CodexManager] Looking for session file for thread: ${this.currentThreadId}`);
57
91
  const sessionFile = await findSessionFile(this.currentThreadId);
58
92
  if (!sessionFile) {
59
- console.warn(`Session file not found for thread ${this.currentThreadId}`);
93
+ console.warn(`[CodexManager] WARNING: Session file not found for thread ${this.currentThreadId}`);
60
94
  return {
61
95
  thread_id: this.currentThreadId,
62
96
  events: [],
63
97
  };
64
98
  }
65
- console.log(`Reading session file: ${sessionFile}`);
99
+ console.log(`[CodexManager] Reading session file: ${sessionFile}`);
66
100
  const events = await readJSONL(sessionFile);
101
+ console.log(`[CodexManager] Read ${events.length} events from session file`);
102
+ const filteredEvents = events.filter((event) => {
103
+ const eventStr = JSON.stringify(event);
104
+ return !eventStr.includes('<replicas_important_instructions>');
105
+ });
106
+ const filteredCount = events.length - filteredEvents.length;
107
+ if (filteredCount > 0) {
108
+ console.log(`[CodexManager] Filtered out ${filteredCount} priming events`);
109
+ }
110
+ console.log(`[CodexManager] Returning ${filteredEvents.length} events`);
67
111
  return {
68
112
  thread_id: this.currentThreadId,
69
- events,
113
+ events: filteredEvents,
70
114
  };
71
115
  }
72
116
  async getStatus() {
117
+ console.log('[CodexManager] getStatus called');
73
118
  let sessionFile = null;
74
119
  if (this.currentThreadId) {
120
+ console.log(`[CodexManager] Checking for session file for thread: ${this.currentThreadId}`);
75
121
  sessionFile = await findSessionFile(this.currentThreadId);
122
+ if (sessionFile) {
123
+ console.log(`[CodexManager] Session file found: ${sessionFile}`);
124
+ }
125
+ else {
126
+ console.log('[CodexManager] Session file not found');
127
+ }
76
128
  }
77
- return {
129
+ else {
130
+ console.log('[CodexManager] No active thread ID');
131
+ }
132
+ const status = {
78
133
  has_active_thread: this.currentThreadId !== null,
79
134
  thread_id: this.currentThreadId,
80
135
  session_file: sessionFile,
81
136
  working_directory: this.workingDirectory,
82
137
  };
138
+ console.log(`[CodexManager] Status: ${JSON.stringify(status)}`);
139
+ return status;
83
140
  }
84
141
  reset() {
85
- console.log('Resetting Codex thread');
142
+ console.log(`[CodexManager] Resetting thread (was: ${this.currentThreadId})`);
86
143
  this.currentThread = null;
87
144
  this.currentThreadId = null;
145
+ console.log('[CodexManager] Thread reset complete');
88
146
  }
89
147
  getThreadId() {
90
148
  return this.currentThreadId;
91
149
  }
92
150
  async getUpdates(since) {
151
+ console.log(`[CodexManager] getUpdates called with since: ${since}`);
93
152
  if (!this.currentThreadId) {
153
+ console.log('[CodexManager] No active thread, returning empty updates');
94
154
  return {
95
155
  events: [],
96
156
  isComplete: true,
@@ -98,20 +158,24 @@ export class CodexManager {
98
158
  }
99
159
  const sessionFile = await findSessionFile(this.currentThreadId);
100
160
  if (!sessionFile) {
161
+ console.log('[CodexManager] Session file not found, returning empty updates');
101
162
  return {
102
163
  events: [],
103
164
  isComplete: true,
104
165
  };
105
166
  }
106
167
  const allEvents = await readJSONL(sessionFile);
168
+ console.log(`[CodexManager] Read ${allEvents.length} total events`);
107
169
  // Filter events that occurred after the 'since' timestamp
108
170
  const filteredEvents = allEvents.filter((event) => {
109
171
  return event.timestamp > since;
110
172
  });
173
+ console.log(`[CodexManager] Found ${filteredEvents.length} events since ${since}`);
111
174
  // Check if thread is complete by looking for turn.completed or error events
112
175
  const isComplete = this.currentThread === null ||
113
176
  allEvents.some((event) => event.type === 'event_msg' &&
114
177
  (event.payload?.type === 'turn.completed' || event.payload?.type === 'error'));
178
+ console.log(`[CodexManager] Thread complete: ${isComplete}`);
115
179
  return {
116
180
  events: filteredEvents,
117
181
  isComplete,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",