@playcraft/cli 0.0.59 → 0.1.1
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 +14 -2
- package/dist/agent/local-backend.js +1 -1
- package/dist/utils/agent-api-client.js +50 -7
- package/dist/utils/tool-operation-journal.js +82 -16
- package/dist/workspace-runtime/codex/app-server.js +135 -169
- package/dist/workspace-runtime/codex/jsonrpc-stdio.js +19 -2
- package/dist/workspace-runtime/codex/launcher-client.js +155 -0
- package/dist/workspace-runtime/codex/loopback.js +118 -37
- package/dist/workspace-runtime/codex/native-adapter.js +3 -0
- package/dist/workspace-runtime/persistence/journal.js +213 -200
- package/dist/workspace-runtime/persistence/sqlite-client.js +61 -0
- package/dist/workspace-runtime/persistence/sqlite-worker.js +1025 -0
- package/dist/workspace-runtime/serve.js +35 -1
- package/dist/workspace-runtime/server/desktop-host.js +314 -0
- package/dist/workspace-runtime/server/dispatch.js +108 -48
- package/dist/workspace-runtime/server/http.js +260 -12
- package/dist/workspace-runtime/server/terminal-host.js +243 -0
- package/dist/workspace-runtime/workspaces/git-credential-broker.js +276 -0
- package/dist/workspace-runtime/workspaces/git-credential-helper.js +66 -0
- package/dist/workspace-runtime/workspaces/git-direct-store.js +154 -0
- package/dist/workspace-runtime/workspaces/git.js +16 -3
- package/dist/workspace-runtime/workspaces/prepare.js +29 -172
- package/dist/workspace-runtime/workspaces/registry.js +12 -2
- package/package.json +7 -4
|
@@ -1,59 +1,140 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { projectNativeThread } from '@playcraft/common/cloud-workspace/runtime';
|
|
2
|
+
import { collectedEvent } from './native-adapter.js';
|
|
2
3
|
/** In-process Codex stand-in. Not the App Server; used to prove the operation/event loop. */
|
|
3
4
|
export function createLoopbackNativeAdapter() {
|
|
4
5
|
const threads = new Map();
|
|
5
6
|
const approvals = new Set();
|
|
7
|
+
const collected = new Set();
|
|
8
|
+
const sent = new Set();
|
|
9
|
+
let turnStarts = 0;
|
|
10
|
+
function emit(event) {
|
|
11
|
+
for (const listener of collected)
|
|
12
|
+
listener(event);
|
|
13
|
+
}
|
|
6
14
|
return {
|
|
7
15
|
name: 'loopback',
|
|
8
16
|
ready: () => true,
|
|
17
|
+
onCollected(listener) {
|
|
18
|
+
collected.add(listener);
|
|
19
|
+
return () => collected.delete(listener);
|
|
20
|
+
},
|
|
21
|
+
turnStartSends() {
|
|
22
|
+
return turnStarts;
|
|
23
|
+
},
|
|
9
24
|
async startThread(input) {
|
|
10
25
|
const threadId = `thread_${input.sessionId}`;
|
|
11
|
-
threads.set(threadId, input.sessionId);
|
|
26
|
+
threads.set(threadId, { sessionId: input.sessionId, items: [] });
|
|
12
27
|
return { threadId };
|
|
13
28
|
},
|
|
14
29
|
async startTurn(input) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
if (input.simulateLostReceipt) {
|
|
22
|
-
|
|
30
|
+
const thread = threads.get(input.threadId);
|
|
31
|
+
if (!thread || thread.sessionId !== input.sessionId)
|
|
32
|
+
return { outcome: 'failed', error: 'unknown_thread' };
|
|
33
|
+
const nativeRequestId = `loopback:${input.sessionId}:${input.clientRequestId}`;
|
|
34
|
+
const sentKey = `${input.sessionId}:${input.clientRequestId}`;
|
|
35
|
+
await input.persistReservation({ nativeRequestId });
|
|
36
|
+
if (input.simulateLostReceipt || sent.has(sentKey)) {
|
|
37
|
+
sent.add(sentKey);
|
|
38
|
+
return { outcome: 'uncertain', threadId: input.threadId };
|
|
23
39
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
sent.add(sentKey);
|
|
41
|
+
turnStarts += 1;
|
|
42
|
+
const turnId = `turn_${input.sessionId}_${input.clientRequestId}`;
|
|
43
|
+
thread.turnId = turnId;
|
|
44
|
+
thread.items.push({
|
|
45
|
+
type: 'userMessage',
|
|
46
|
+
id: `user_${turnId}`,
|
|
47
|
+
content: [{ type: 'text', text: input.text }],
|
|
48
|
+
});
|
|
49
|
+
if (!input.text.includes('[approval]')) {
|
|
50
|
+
thread.items.push({
|
|
51
|
+
type: 'agentMessage',
|
|
52
|
+
id: `agent_${turnId}`,
|
|
53
|
+
text: `loopback:${input.text}`,
|
|
54
|
+
});
|
|
34
55
|
}
|
|
35
|
-
|
|
56
|
+
queueMicrotask(() => {
|
|
57
|
+
emit(collectedEvent('notification', 'item/agentMessage/delta', {
|
|
58
|
+
threadId: input.threadId,
|
|
59
|
+
turnId,
|
|
60
|
+
text: `loopback:${input.text}`,
|
|
61
|
+
delta: `loopback:${input.text}`,
|
|
62
|
+
}));
|
|
63
|
+
if (input.text.includes('[approval]')) {
|
|
64
|
+
const approvalId = `approval_${input.clientRequestId}`;
|
|
65
|
+
approvals.add(JSON.stringify([input.sessionId, approvalId]));
|
|
66
|
+
emit(collectedEvent('approval_request', 'item/tool/requestUserInput', {
|
|
67
|
+
threadId: input.threadId,
|
|
68
|
+
turnId,
|
|
69
|
+
approvalId,
|
|
70
|
+
itemId: approvalId,
|
|
71
|
+
}));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
emit(collectedEvent('notification', 'turn/completed', {
|
|
75
|
+
threadId: input.threadId,
|
|
76
|
+
turnId,
|
|
77
|
+
turn: { id: turnId, status: 'completed' },
|
|
78
|
+
}));
|
|
79
|
+
});
|
|
80
|
+
return { outcome: 'accepted', threadId: input.threadId, turnId };
|
|
36
81
|
},
|
|
37
82
|
async interrupt(input) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
const thread = threads.get(input.threadId);
|
|
84
|
+
if (!thread || thread.sessionId !== input.sessionId)
|
|
85
|
+
return { outcome: 'uncertain' };
|
|
86
|
+
const turnId = thread.turnId;
|
|
87
|
+
queueMicrotask(() => {
|
|
88
|
+
emit(collectedEvent('notification', 'turn/completed', {
|
|
89
|
+
threadId: input.threadId,
|
|
90
|
+
turnId,
|
|
91
|
+
turn: { id: turnId, status: 'interrupted' },
|
|
92
|
+
}));
|
|
93
|
+
});
|
|
94
|
+
return { outcome: 'accepted', turnId };
|
|
45
95
|
},
|
|
46
96
|
async respondApproval(input) {
|
|
47
|
-
|
|
48
|
-
|
|
97
|
+
const key = JSON.stringify([input.sessionId, input.approvalId]);
|
|
98
|
+
if (!approvals.has(key))
|
|
99
|
+
return { outcome: 'failed', approvalId: input.approvalId };
|
|
100
|
+
approvals.delete(key);
|
|
101
|
+
const thread = [...threads].find(([, value]) => value.sessionId === input.sessionId);
|
|
102
|
+
queueMicrotask(() => {
|
|
103
|
+
emit(collectedEvent('notification', 'approval.resolved', {
|
|
104
|
+
approvalId: input.approvalId,
|
|
105
|
+
accepted: input.accepted,
|
|
106
|
+
threadId: thread?.[0],
|
|
107
|
+
turnId: thread?.[1].turnId,
|
|
108
|
+
}));
|
|
109
|
+
emit(collectedEvent('notification', 'item/agentMessage/delta', {
|
|
110
|
+
threadId: thread?.[0],
|
|
111
|
+
turnId: thread?.[1].turnId,
|
|
112
|
+
delta: 'after-approval',
|
|
113
|
+
}));
|
|
114
|
+
emit(collectedEvent('notification', 'turn/completed', {
|
|
115
|
+
threadId: thread?.[0],
|
|
116
|
+
turnId: thread?.[1].turnId,
|
|
117
|
+
turn: { id: thread?.[1].turnId, status: 'completed' },
|
|
118
|
+
}));
|
|
119
|
+
});
|
|
120
|
+
const found = thread?.[1];
|
|
121
|
+
if (found) {
|
|
122
|
+
found.items.push({
|
|
123
|
+
type: 'agentMessage',
|
|
124
|
+
id: `agent_${found.turnId ?? input.approvalId}`,
|
|
125
|
+
text: 'after-approval',
|
|
126
|
+
});
|
|
49
127
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return
|
|
128
|
+
return { outcome: 'accepted', approvalId: input.approvalId, turnId: found?.turnId };
|
|
129
|
+
},
|
|
130
|
+
async readThread(input) {
|
|
131
|
+
const thread = threads.get(input.threadId);
|
|
132
|
+
if (!thread || thread.sessionId !== input.sessionId)
|
|
133
|
+
return undefined;
|
|
134
|
+
return projectNativeThread(input.threadId, {
|
|
135
|
+
id: input.threadId,
|
|
136
|
+
turns: [{ items: thread.items }],
|
|
137
|
+
});
|
|
57
138
|
},
|
|
58
139
|
};
|
|
59
140
|
}
|