@jigging/jig 0.1.0-alpha.5 → 0.1.0-alpha.7
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 +10 -6
- package/THIRD_PARTY_NOTICES +40 -1
- package/libexec/agent/claude-agent-acp.LICENSE +191 -0
- package/libexec/agent/claude-agent-acp.js +71361 -0
- package/libexec/agent/claude-agent-launcher.js +53 -0
- package/libexec/agent/claude-agent-sdk.LICENSE +1 -0
- package/libexec/agent/codex-acp.LICENSE +190 -0
- package/libexec/agent/codex-acp.js +34238 -0
- package/libexec/agent/codex-agent-launcher.js +54 -0
- package/libexec/agent/codex-requirements.toml +5 -0
- package/libexec/agent/{openrouter-responses-worker.js → openai-responses-worker.js} +196 -75
- package/libexec/agent/pi-acp.LICENSE +21 -0
- package/libexec/agent/pi-acp.js +16468 -0
- package/libexec/agent/pi-agent-launcher.js +196 -0
- package/libexec/installed-cli.js +20604 -1420
- package/libexec/linux-rootless-supervisor.js +4 -5
- package/package.json +20 -4
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/jig-runtime/bun
|
|
2
|
+
// @bun
|
|
3
|
+
|
|
4
|
+
// src/internal/pi-agent-launcher.ts
|
|
5
|
+
import {
|
|
6
|
+
closeSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
openSync,
|
|
9
|
+
readSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
writeSync
|
|
12
|
+
} from "fs";
|
|
13
|
+
import { spawn } from "child_process";
|
|
14
|
+
var STARTUP_INPUT_BYTES = 64 * 1024;
|
|
15
|
+
var PI_HOME = "/tmp/pi-home";
|
|
16
|
+
var PI_AGENT_DIR = "/tmp/pi-agent";
|
|
17
|
+
var CREDENTIAL_PATH = `${PI_AGENT_DIR}/auth.json`;
|
|
18
|
+
var SETTINGS_PATH = `${PI_AGENT_DIR}/settings.json`;
|
|
19
|
+
var MODELS_PATH = `${PI_AGENT_DIR}/models.json`;
|
|
20
|
+
var NATIVE_PI_PATH = "/agent/pi";
|
|
21
|
+
var ADAPTER_SPECIFIER = "./pi-acp.js";
|
|
22
|
+
var MAX_OUTPUT_TOKENS = 4096;
|
|
23
|
+
var PROVIDER = /^[a-z0-9][a-z0-9._-]{0,127}$/;
|
|
24
|
+
var SELECTION = /^[A-Za-z0-9][A-Za-z0-9._:/+-]{0,255}$/;
|
|
25
|
+
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
26
|
+
var PRIVATE_PI_NATIVE_ARGUMENTS = Object.freeze([
|
|
27
|
+
"--mode",
|
|
28
|
+
"rpc",
|
|
29
|
+
"--no-session",
|
|
30
|
+
"--no-tools",
|
|
31
|
+
"--no-extensions",
|
|
32
|
+
"--no-skills",
|
|
33
|
+
"--no-prompt-templates",
|
|
34
|
+
"--no-themes",
|
|
35
|
+
"--no-context-files",
|
|
36
|
+
"--no-approve",
|
|
37
|
+
"--offline"
|
|
38
|
+
]);
|
|
39
|
+
var PRIVATE_PI_SETTINGS = Object.freeze({
|
|
40
|
+
defaultProjectTrust: "never",
|
|
41
|
+
enableAnalytics: false,
|
|
42
|
+
enableInstallTelemetry: false,
|
|
43
|
+
enableSkillCommands: false,
|
|
44
|
+
extensions: Object.freeze([]),
|
|
45
|
+
packages: Object.freeze([]),
|
|
46
|
+
prompts: Object.freeze([]),
|
|
47
|
+
quietStartup: true,
|
|
48
|
+
retry: Object.freeze({
|
|
49
|
+
enabled: false,
|
|
50
|
+
maxRetries: 0,
|
|
51
|
+
provider: Object.freeze({ maxRetries: 0 })
|
|
52
|
+
}),
|
|
53
|
+
skills: Object.freeze([]),
|
|
54
|
+
themes: Object.freeze([]),
|
|
55
|
+
compaction: Object.freeze({ enabled: false }),
|
|
56
|
+
images: Object.freeze({ blockImages: true })
|
|
57
|
+
});
|
|
58
|
+
if (import.meta.main)
|
|
59
|
+
await main();
|
|
60
|
+
async function main() {
|
|
61
|
+
const startup = process.env.JIG_PI_STARTUP_INPUT;
|
|
62
|
+
if (startup === undefined) {
|
|
63
|
+
await launchNativePi();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (startup !== "credential")
|
|
67
|
+
throw new Error("Pi startup input mode is invalid");
|
|
68
|
+
const provider = requireProvider(process.env.JIG_PI_PROVIDER);
|
|
69
|
+
const model = requireSelection(process.env.JIG_PI_MODEL, "Pi model");
|
|
70
|
+
mkdirSync(PI_HOME, { recursive: false, mode: 448 });
|
|
71
|
+
mkdirSync(PI_AGENT_DIR, { recursive: false, mode: 448 });
|
|
72
|
+
materializeCredential(provider);
|
|
73
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(PRIVATE_PI_SETTINGS), {
|
|
74
|
+
encoding: "utf8",
|
|
75
|
+
flag: "wx",
|
|
76
|
+
mode: 384
|
|
77
|
+
});
|
|
78
|
+
writeFileSync(MODELS_PATH, JSON.stringify(privatePiModels(provider, model)), {
|
|
79
|
+
encoding: "utf8",
|
|
80
|
+
flag: "wx",
|
|
81
|
+
mode: 384
|
|
82
|
+
});
|
|
83
|
+
delete process.env.JIG_PI_STARTUP_INPUT;
|
|
84
|
+
await import(ADAPTER_SPECIFIER);
|
|
85
|
+
}
|
|
86
|
+
function privatePiModels(provider, model) {
|
|
87
|
+
return {
|
|
88
|
+
providers: {
|
|
89
|
+
[requireProvider(provider)]: {
|
|
90
|
+
modelOverrides: {
|
|
91
|
+
[requireSelection(model, "Pi model")]: { maxTokens: MAX_OUTPUT_TOKENS }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function materializeCredential(provider) {
|
|
98
|
+
const header = readExactly(4);
|
|
99
|
+
const size = new DataView(header.buffer, header.byteOffset, header.byteLength).getUint32(0, false);
|
|
100
|
+
if (size === 0 || size > STARTUP_INPUT_BYTES - 4) {
|
|
101
|
+
throw new Error("Pi startup input is invalid");
|
|
102
|
+
}
|
|
103
|
+
const credential = readExactly(size);
|
|
104
|
+
let descriptor;
|
|
105
|
+
try {
|
|
106
|
+
const parsed = JSON.parse(decoder.decode(credential));
|
|
107
|
+
if (!isRecord(parsed) || !exactKeys(parsed, [provider])) {
|
|
108
|
+
throw new Error("Pi startup input is invalid");
|
|
109
|
+
}
|
|
110
|
+
const entry = parsed[provider];
|
|
111
|
+
if (!isRecord(entry) || entry.type !== (provider === "openrouter" ? "api_key" : "oauth")) {
|
|
112
|
+
throw new Error("Pi startup input is invalid");
|
|
113
|
+
}
|
|
114
|
+
descriptor = openSync(CREDENTIAL_PATH, "wx", 384);
|
|
115
|
+
writeExactly(descriptor, credential);
|
|
116
|
+
} catch {
|
|
117
|
+
throw new Error("Pi startup input is invalid");
|
|
118
|
+
} finally {
|
|
119
|
+
credential.fill(0);
|
|
120
|
+
if (descriptor !== undefined)
|
|
121
|
+
closeSync(descriptor);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function launchNativePi() {
|
|
125
|
+
if (process.argv.slice(2).join("\x00") !== ["--mode", "rpc", "--no-themes"].join("\x00")) {
|
|
126
|
+
throw new Error("pi-acp native invocation is invalid");
|
|
127
|
+
}
|
|
128
|
+
const provider = requireProvider(process.env.JIG_PI_PROVIDER);
|
|
129
|
+
const model = requireSelection(process.env.JIG_PI_MODEL, "Pi model");
|
|
130
|
+
const child = spawn(NATIVE_PI_PATH, [
|
|
131
|
+
...PRIVATE_PI_NATIVE_ARGUMENTS,
|
|
132
|
+
"--provider",
|
|
133
|
+
provider,
|
|
134
|
+
"--model",
|
|
135
|
+
model
|
|
136
|
+
], {
|
|
137
|
+
cwd: "/work",
|
|
138
|
+
env: process.env,
|
|
139
|
+
stdio: "inherit"
|
|
140
|
+
});
|
|
141
|
+
const forward = (signal) => {
|
|
142
|
+
if (!child.killed)
|
|
143
|
+
child.kill(signal);
|
|
144
|
+
};
|
|
145
|
+
process.once("SIGINT", forward);
|
|
146
|
+
process.once("SIGTERM", forward);
|
|
147
|
+
const exitCode = await new Promise((resolve, reject) => {
|
|
148
|
+
child.once("error", reject);
|
|
149
|
+
child.once("exit", (code, signal) => resolve(code ?? (signal === null ? 1 : 128)));
|
|
150
|
+
});
|
|
151
|
+
process.removeListener("SIGINT", forward);
|
|
152
|
+
process.removeListener("SIGTERM", forward);
|
|
153
|
+
process.exitCode = exitCode;
|
|
154
|
+
}
|
|
155
|
+
function readExactly(size) {
|
|
156
|
+
const result = new Uint8Array(size);
|
|
157
|
+
let offset = 0;
|
|
158
|
+
while (offset < result.byteLength) {
|
|
159
|
+
const count = readSync(0, result, offset, result.byteLength - offset, null);
|
|
160
|
+
if (count === 0)
|
|
161
|
+
throw new Error("Pi startup input ended early");
|
|
162
|
+
offset += count;
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
function writeExactly(descriptor, value) {
|
|
167
|
+
let offset = 0;
|
|
168
|
+
while (offset < value.byteLength) {
|
|
169
|
+
offset += writeSync(descriptor, value, offset, value.byteLength - offset, null);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function requireProvider(value) {
|
|
173
|
+
if (typeof value !== "string" || !PROVIDER.test(value)) {
|
|
174
|
+
throw new Error("Pi provider is invalid");
|
|
175
|
+
}
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
function requireSelection(value, label) {
|
|
179
|
+
if (typeof value !== "string" || !SELECTION.test(value)) {
|
|
180
|
+
throw new Error(`${label} is invalid`);
|
|
181
|
+
}
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
function exactKeys(value, expected) {
|
|
185
|
+
const keys = Object.keys(value).sort();
|
|
186
|
+
const sorted = [...expected].sort();
|
|
187
|
+
return keys.length === sorted.length && keys.every((key, index) => key === sorted[index]);
|
|
188
|
+
}
|
|
189
|
+
function isRecord(value) {
|
|
190
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
privatePiModels,
|
|
194
|
+
PRIVATE_PI_SETTINGS,
|
|
195
|
+
PRIVATE_PI_NATIVE_ARGUMENTS
|
|
196
|
+
};
|