@junghanacs/entwurf 0.12.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/AGENTS.md +240 -0
- package/BASELINE.md +227 -0
- package/CHANGELOG.md +1210 -0
- package/CONTRIBUTING.md +63 -0
- package/DELIVERY.md +209 -0
- package/LICENSE +21 -0
- package/README.md +504 -0
- package/VERIFY.md +260 -0
- package/demo/README.md +188 -0
- package/demo/demo-baseline.sh +156 -0
- package/demo/demo.sh +183 -0
- package/docs/assets/entwurf-demo.gif +0 -0
- package/docs/assets/entwurf-doomemacs.gif +0 -0
- package/docs/assets/entwurf-entwurf.gif +0 -0
- package/docs/assets/entwurf-hero.jpg +0 -0
- package/docs/setup-clean-host.md +305 -0
- package/mcp/entwurf-bridge/src/index.ts +513 -0
- package/mcp/entwurf-bridge/start.sh +25 -0
- package/mcp/entwurf-bridge/test.sh +54 -0
- package/mcp/tsconfig.json +29 -0
- package/package.json +130 -0
- package/pi/entwurf-capabilities.json +9 -0
- package/pi/entwurf-targets.json +20 -0
- package/pi/meta-bridge/.claude-plugin/marketplace.json +12 -0
- package/pi/meta-bridge/entwurf-meta-receive/.claude-plugin/plugin.json +5 -0
- package/pi/meta-bridge/entwurf-meta-receive/hooks/hooks.json +50 -0
- package/pi/meta-bridge/entwurf-meta-receive/scripts/doorbell.sh +54 -0
- package/pi/settings.reference.json +43 -0
- package/pi/skill-plugin-example/.claude-plugin/plugin.json +4 -0
- package/pi/skill-plugin-example/skills/hello/SKILL.md +18 -0
- package/pi-extensions/acp-provider.ts +63 -0
- package/pi-extensions/entwurf-control.ts +1692 -0
- package/pi-extensions/lib/acp/acp-client.ts +90 -0
- package/pi-extensions/lib/acp/augment.ts +238 -0
- package/pi-extensions/lib/acp/backend-adapter.ts +319 -0
- package/pi-extensions/lib/acp/backend.ts +873 -0
- package/pi-extensions/lib/acp/config.ts +552 -0
- package/pi-extensions/lib/acp/context.ts +177 -0
- package/pi-extensions/lib/acp/engraving.ts +123 -0
- package/pi-extensions/lib/acp/event-mapper.ts +339 -0
- package/pi-extensions/lib/acp/models.ts +102 -0
- package/pi-extensions/lib/acp/overlay.ts +220 -0
- package/pi-extensions/lib/acp/prompts/engraving.md +1 -0
- package/pi-extensions/lib/acp/session-store.ts +418 -0
- package/pi-extensions/lib/acp/tool-surface.ts +184 -0
- package/pi-extensions/lib/entwurf-control-rpc.ts +208 -0
- package/pi-extensions/lib/entwurf-core.ts +2033 -0
- package/pi-extensions/lib/entwurf-deliverability.ts +123 -0
- package/pi-extensions/lib/entwurf-fact-provider.ts +158 -0
- package/pi-extensions/lib/entwurf-facts.ts +251 -0
- package/pi-extensions/lib/entwurf-mailbox-guard.ts +100 -0
- package/pi-extensions/lib/entwurf-peers-render.ts +154 -0
- package/pi-extensions/lib/entwurf-preflight.ts +247 -0
- package/pi-extensions/lib/entwurf-resume-args.ts +88 -0
- package/pi-extensions/lib/entwurf-self-address.ts +117 -0
- package/pi-extensions/lib/entwurf-v2-contract.ts +427 -0
- package/pi-extensions/lib/entwurf-v2-decider.ts +441 -0
- package/pi-extensions/lib/entwurf-v2-lock.ts +412 -0
- package/pi-extensions/lib/entwurf-v2-mailbox.ts +87 -0
- package/pi-extensions/lib/entwurf-v2-production.ts +326 -0
- package/pi-extensions/lib/entwurf-v2-release.ts +149 -0
- package/pi-extensions/lib/entwurf-v2-resume-marker.ts +34 -0
- package/pi-extensions/lib/entwurf-v2-runner.ts +196 -0
- package/pi-extensions/lib/entwurf-v2-send-fallback.ts +166 -0
- package/pi-extensions/lib/entwurf-v2-send.ts +271 -0
- package/pi-extensions/lib/entwurf-v2-spawn-production.ts +337 -0
- package/pi-extensions/lib/entwurf-v2-spawn.ts +323 -0
- package/pi-extensions/lib/entwurf-v2-surface.ts +205 -0
- package/pi-extensions/lib/meta-mailbox-body.ts +80 -0
- package/pi-extensions/lib/meta-session.ts +1951 -0
- package/pi-extensions/lib/project-trust-handler.ts +154 -0
- package/pi-extensions/lib/session-id.js +57 -0
- package/pi-extensions/lib/socket-discovery.ts +346 -0
- package/pi-extensions/lib/socket-probe.ts +92 -0
- package/pi-extensions/meta-bridge-hook.ts +250 -0
- package/pi-extensions/model-lock.ts +235 -0
- package/prompts/engraving.md +27 -0
- package/protocol.js +31 -0
- package/run.sh +2832 -0
- package/scripts/check-acp-backend-preflight.ts +130 -0
- package/scripts/check-acp-carrier-augment.ts +297 -0
- package/scripts/check-acp-config.ts +322 -0
- package/scripts/check-acp-event-mapper.ts +253 -0
- package/scripts/check-acp-overlay.ts +154 -0
- package/scripts/check-acp-prompt-builder.ts +191 -0
- package/scripts/check-acp-provider-surface.ts +159 -0
- package/scripts/check-acp-sdk-surface.ts +211 -0
- package/scripts/check-acp-session-reuse.ts +756 -0
- package/scripts/check-acp-session-store.ts +387 -0
- package/scripts/check-acp-tool-surface.ts +159 -0
- package/scripts/check-entwurf-bridge-boot.ts +199 -0
- package/scripts/check-entwurf-capabilities.ts +123 -0
- package/scripts/check-entwurf-control-rpc.ts +187 -0
- package/scripts/check-entwurf-deliverability.ts +158 -0
- package/scripts/check-entwurf-fact-provider.ts +316 -0
- package/scripts/check-entwurf-facts.ts +358 -0
- package/scripts/check-entwurf-mailbox-guard.ts +264 -0
- package/scripts/check-entwurf-peers-surface.ts +235 -0
- package/scripts/check-entwurf-resume-args.ts +149 -0
- package/scripts/check-entwurf-self-address.ts +209 -0
- package/scripts/check-entwurf-session-identity.ts +703 -0
- package/scripts/check-entwurf-v2-contract.ts +536 -0
- package/scripts/check-entwurf-v2-decider.ts +795 -0
- package/scripts/check-entwurf-v2-lock.ts +368 -0
- package/scripts/check-entwurf-v2-mailbox.ts +228 -0
- package/scripts/check-entwurf-v2-matrix.ts +437 -0
- package/scripts/check-entwurf-v2-production.ts +406 -0
- package/scripts/check-entwurf-v2-release.ts +245 -0
- package/scripts/check-entwurf-v2-runner.ts +452 -0
- package/scripts/check-entwurf-v2-send-fallback.ts +371 -0
- package/scripts/check-entwurf-v2-send.ts +454 -0
- package/scripts/check-entwurf-v2-spawn-production.ts +452 -0
- package/scripts/check-entwurf-v2-spawn.ts +398 -0
- package/scripts/check-entwurf-v2-surface.ts +352 -0
- package/scripts/check-keyset-overlap.py +120 -0
- package/scripts/check-mailbox-receipt-state.ts +170 -0
- package/scripts/check-meta-capability-source.ts +112 -0
- package/scripts/check-meta-dual-consumers.ts +154 -0
- package/scripts/check-meta-dual-read.ts +158 -0
- package/scripts/check-meta-listing.ts +138 -0
- package/scripts/check-meta-mailbox-state-write.ts +135 -0
- package/scripts/check-meta-migration.ts +212 -0
- package/scripts/check-meta-receiver-marker.ts +185 -0
- package/scripts/check-meta-record-v2.ts +191 -0
- package/scripts/check-meta-session.ts +673 -0
- package/scripts/check-model-lock.ts +408 -0
- package/scripts/check-package-source-routing.ts +253 -0
- package/scripts/check-pi-preflight.ts +304 -0
- package/scripts/check-project-trust-handler.ts +265 -0
- package/scripts/check-shell-quote.ts +121 -0
- package/scripts/check-socket-discovery.ts +428 -0
- package/scripts/check-socket-probe.ts +106 -0
- package/scripts/fixtures/probe-mcp-server.ts +33 -0
- package/scripts/gnew-rpc-drive.ts +211 -0
- package/scripts/lib/acp-child-cleanup.ts +116 -0
- package/scripts/meta-bridge-doctor.sh +315 -0
- package/scripts/meta-bridge-hook-log.sh +26 -0
- package/scripts/meta-bridge-install.sh +135 -0
- package/scripts/meta-bridge-prune.ts +199 -0
- package/scripts/meta-bridge-state.py +549 -0
- package/scripts/meta-bridge-statusline.sh +192 -0
- package/scripts/meta-bridge-store-doctor.ts +64 -0
- package/scripts/meta-bridge-uninstall.sh +39 -0
- package/scripts/new-session-id.ts +25 -0
- package/scripts/postinstall-chmod.cjs +58 -0
- package/scripts/raw-async-delivery/README.md +258 -0
- package/scripts/raw-async-delivery/cc-enqueue-addressed.sh +35 -0
- package/scripts/raw-async-delivery/cc-mailbox-rewake.sh +38 -0
- package/scripts/raw-async-delivery/cc-watch-filechanged.sh +19 -0
- package/scripts/raw-async-delivery/cc-watch-sessionstart.sh +15 -0
- package/scripts/raw-async-delivery/codex-local-appserver.sh +39 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/.claude-plugin/plugin.json +5 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/hooks/hooks.json +28 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/scripts/watch-filechanged.sh +28 -0
- package/scripts/raw-async-delivery/plugin-entwurf-receive/scripts/watch-sessionstart.sh +27 -0
- package/scripts/raw-async-delivery/raw-agy-send.sh +29 -0
- package/scripts/raw-async-delivery/raw-claude-enqueue.sh +30 -0
- package/scripts/raw-async-delivery/raw-codex-ws-turn-start.py +164 -0
- package/scripts/raw-async-delivery/repro-addressed-routing.sh +96 -0
- package/scripts/raw-async-delivery/repro-plugin-idle-wake.sh +104 -0
- package/scripts/resolve-acp-bridge.ts +25 -0
- package/scripts/smoke-acp-bundled-mcp-live.ts +292 -0
- package/scripts/smoke-acp-carrier-augment-live.ts +192 -0
- package/scripts/smoke-acp-mcp-live.ts +129 -0
- package/scripts/smoke-acp-memory-containment-live.ts +389 -0
- package/scripts/smoke-acp-overlay-live.ts +314 -0
- package/scripts/smoke-acp-provider-live.ts +162 -0
- package/scripts/smoke-acp-raw-turn-live.ts +261 -0
- package/scripts/smoke-acp-session-reuse-live.ts +172 -0
- package/scripts/smoke-acp-skill-live.ts +144 -0
- package/scripts/smoke-acp-socket-citizen-live.ts +168 -0
- package/scripts/smoke-claude-native-resume-live.sh +198 -0
- package/scripts/smoke-entwurf-v2-matrix-live.ts +398 -0
- package/scripts/smoke-entwurf-v2-spawn-live.ts +175 -0
- package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +428 -0
- package/scripts/smoke-meta-async-drift.sh +171 -0
- package/scripts/smoke-meta-honesty.sh +147 -0
- package/scripts/smoke-meta-install-state.sh +403 -0
- package/scripts/smoke-meta-keyset-guard.sh +111 -0
- package/scripts/smoke-meta-prune.sh +174 -0
- package/scripts/smoke-resident-garden-guard.sh +433 -0
- package/scripts/smoke-session-id-name.ts +187 -0
- package/scripts/tsconfig.json +34 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* entwurf-control-rpc — the `--entwurf-control` socket protocol SSOT: the wire types
|
|
3
|
+
* (`SenderEnvelope`, `RpcResponse`, the `Rpc*Command` union) AND the newline-delimited-JSON
|
|
4
|
+
* client `sendRpcCommand`, extracted VERBATIM from `entwurf-control.ts` (no logic change).
|
|
5
|
+
*
|
|
6
|
+
* Why a ctx-free lib: the 5d entwurf_v2 production `sendOverSocket` dep needs the same RPC
|
|
7
|
+
* client the legacy control-send + session commands use, but the v2 production assembly
|
|
8
|
+
* lives in `lib/` (ctx-free, gate-/smoke-testable) and must NOT import the surface file's
|
|
9
|
+
* `ExtensionContext`/`ExtensionAPI` world. Keeping ONE wire-protocol definition here means
|
|
10
|
+
* the legacy callers and the v2 producer share one SSOT — the types and the framing never
|
|
11
|
+
* fork. `entwurf-control.ts` re-exports `SenderEnvelope` so its public surface is unchanged.
|
|
12
|
+
*
|
|
13
|
+
* This module performs NO IO of its own beyond the single `net` client connection it is
|
|
14
|
+
* asked to open, and touches nothing pi-specific — it is a pure transport over a path.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as net from "node:net";
|
|
18
|
+
|
|
19
|
+
// `sender` carries the transparency envelope (agentId / sessionId / cwd /
|
|
20
|
+
// timestamp). All four fields are mandatory whenever `sender` is present —
|
|
21
|
+
// see handleCommand("send") for the reject path. `wants_reply` is a separate
|
|
22
|
+
// etiquette marker (NOT part of the envelope), default false — see
|
|
23
|
+
// handleCommand("send") + parseSenderInfo and the SenderInfo block below for
|
|
24
|
+
// the full semantics: human-conversation hint only, no wait, no polling, no
|
|
25
|
+
// delivery tracking. `<sender_info>` JSON synthesis happens at the receiver
|
|
26
|
+
// side so callers never have to mangle the message body; entwurf-bridge
|
|
27
|
+
// passes the envelope through and the receiving pi prepends the canonical
|
|
28
|
+
// XML-style payload before handing the customMessage to pi.sendMessage.
|
|
29
|
+
export interface SenderEnvelope {
|
|
30
|
+
sessionId: string;
|
|
31
|
+
agentId: string;
|
|
32
|
+
cwd: string;
|
|
33
|
+
timestamp: string; // ISO 8601 UTC
|
|
34
|
+
origin?: "pi-session" | "external-mcp" | "meta-session";
|
|
35
|
+
replyable?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface RpcResponse {
|
|
39
|
+
type: "response";
|
|
40
|
+
command: string;
|
|
41
|
+
success: boolean;
|
|
42
|
+
error?: string;
|
|
43
|
+
data?: unknown;
|
|
44
|
+
id?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Unified command structure
|
|
48
|
+
export interface RpcSendCommand {
|
|
49
|
+
type: "send";
|
|
50
|
+
message: string;
|
|
51
|
+
mode?: "steer" | "follow_up";
|
|
52
|
+
sender?: SenderEnvelope;
|
|
53
|
+
wants_reply?: boolean;
|
|
54
|
+
id?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface RpcGetMessageCommand {
|
|
58
|
+
type: "get_message";
|
|
59
|
+
id?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface RpcClearCommand {
|
|
63
|
+
type: "clear";
|
|
64
|
+
summarize?: boolean;
|
|
65
|
+
id?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface RpcAbortCommand {
|
|
69
|
+
type: "abort";
|
|
70
|
+
id?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface RpcGetInfoCommand {
|
|
74
|
+
type: "get_info";
|
|
75
|
+
id?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type RpcCommand = RpcSendCommand | RpcGetMessageCommand | RpcClearCommand | RpcAbortCommand | RpcGetInfoCommand;
|
|
79
|
+
|
|
80
|
+
export interface RpcClientOptions {
|
|
81
|
+
timeout?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ControlSocketRuntimeInfo {
|
|
85
|
+
cwd?: string;
|
|
86
|
+
modelId?: string;
|
|
87
|
+
modelProvider?: string;
|
|
88
|
+
idle?: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function parseGetInfoResponseData(data: unknown): ControlSocketRuntimeInfo {
|
|
92
|
+
const value = data as
|
|
93
|
+
| {
|
|
94
|
+
cwd?: unknown;
|
|
95
|
+
model?: { id?: unknown; provider?: unknown } | null;
|
|
96
|
+
idle?: unknown;
|
|
97
|
+
}
|
|
98
|
+
| undefined;
|
|
99
|
+
return {
|
|
100
|
+
cwd: typeof value?.cwd === "string" ? value.cwd : undefined,
|
|
101
|
+
modelId: typeof value?.model?.id === "string" ? value.model.id : undefined,
|
|
102
|
+
modelProvider: typeof value?.model?.provider === "string" ? value.model.provider : undefined,
|
|
103
|
+
idle: typeof value?.idle === "boolean" ? value.idle : undefined,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function formatRuntimeModel(
|
|
108
|
+
info: Pick<ControlSocketRuntimeInfo, "modelId" | "modelProvider">,
|
|
109
|
+
): string | undefined {
|
|
110
|
+
if (info.modelProvider && info.modelId) return `${info.modelProvider}/${info.modelId}`;
|
|
111
|
+
return info.modelId;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function fetchControlSocketRuntimeInfo(
|
|
115
|
+
socketPath: string,
|
|
116
|
+
options: RpcClientOptions = {},
|
|
117
|
+
): Promise<ControlSocketRuntimeInfo> {
|
|
118
|
+
const result = await sendRpcCommand(socketPath, { type: "get_info" }, { timeout: options.timeout ?? 1500 });
|
|
119
|
+
if (!result.response.success) {
|
|
120
|
+
throw new Error(result.response.error ?? "get_info failed");
|
|
121
|
+
}
|
|
122
|
+
return parseGetInfoResponseData(result.response.data);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export async function sendRpcCommand(
|
|
126
|
+
socketPath: string,
|
|
127
|
+
command: RpcCommand,
|
|
128
|
+
options: RpcClientOptions = {},
|
|
129
|
+
): Promise<{ response: RpcResponse }> {
|
|
130
|
+
const { timeout = 5000 } = options;
|
|
131
|
+
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
const socket = net.createConnection(socketPath);
|
|
134
|
+
socket.setEncoding("utf8");
|
|
135
|
+
|
|
136
|
+
const timeoutHandle = setTimeout(() => {
|
|
137
|
+
socket.destroy(new Error("timeout"));
|
|
138
|
+
}, timeout);
|
|
139
|
+
|
|
140
|
+
let buffer = "";
|
|
141
|
+
// settled guard: a single Promise can only be resolved or rejected
|
|
142
|
+
// once. close/error/timeout/data can all race to terminate the RPC,
|
|
143
|
+
// so every terminal path goes through doResolve/doReject which
|
|
144
|
+
// short-circuits if we have already settled. Without this, the
|
|
145
|
+
// natural close event that follows a clean resolve would try to
|
|
146
|
+
// reject a settled promise (silent under V8) or — worse — duplicate
|
|
147
|
+
// listeners would attempt to write on a destroyed socket.
|
|
148
|
+
let settled = false;
|
|
149
|
+
|
|
150
|
+
const doResolve = (value: { response: RpcResponse }) => {
|
|
151
|
+
if (settled) return;
|
|
152
|
+
settled = true;
|
|
153
|
+
clearTimeout(timeoutHandle);
|
|
154
|
+
socket.removeAllListeners();
|
|
155
|
+
socket.end();
|
|
156
|
+
resolve(value);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const doReject = (error: Error) => {
|
|
160
|
+
if (settled) return;
|
|
161
|
+
settled = true;
|
|
162
|
+
clearTimeout(timeoutHandle);
|
|
163
|
+
socket.removeAllListeners();
|
|
164
|
+
socket.destroy();
|
|
165
|
+
reject(error);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
socket.on("connect", () => {
|
|
169
|
+
socket.write(`${JSON.stringify(command)}\n`);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
socket.on("data", (chunk) => {
|
|
173
|
+
buffer += chunk;
|
|
174
|
+
let newlineIndex = buffer.indexOf("\n");
|
|
175
|
+
while (newlineIndex !== -1) {
|
|
176
|
+
const line = buffer.slice(0, newlineIndex).trim();
|
|
177
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
178
|
+
newlineIndex = buffer.indexOf("\n");
|
|
179
|
+
if (!line) continue;
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
const msg = JSON.parse(line);
|
|
183
|
+
if (msg.type === "response" && msg.command === command.type) {
|
|
184
|
+
doResolve({ response: msg });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
} catch {
|
|
188
|
+
// Ignore parse errors, keep waiting
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Server closed the connection before any response arrived. Without
|
|
194
|
+
// this branch the caller's only failure signal would be the
|
|
195
|
+
// configured wait timeout, which is exactly the failure mode the
|
|
196
|
+
// 2026-05-18 receiver-side stuck incident surfaced through. The
|
|
197
|
+
// settled guard makes this a no-op when we already resolved
|
|
198
|
+
// cleanly — every successful RPC ends with socket.end() and
|
|
199
|
+
// triggers a natural close.
|
|
200
|
+
socket.on("close", () => {
|
|
201
|
+
doReject(new Error("connection closed before response"));
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
socket.on("error", (error) => {
|
|
205
|
+
doReject(error);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
}
|