@andreroggeri/adapter-pi-local-serialized 0.1.0 → 0.1.2
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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/server/concurrency.d.ts.map +1 -1
- package/dist/server/concurrency.js +27 -3
- package/dist/server/concurrency.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdapterModelProfileDefinition } from "@paperclipai/adapter-utils";
|
|
1
|
+
import type { AdapterModelProfileDefinition, ServerAdapterModule } from "@paperclipai/adapter-utils";
|
|
2
2
|
export declare const type = "pi_local_serialized";
|
|
3
3
|
export declare const label = "Pi (local, serialized)";
|
|
4
4
|
export declare const SANDBOX_INSTALL_COMMAND = "npm install -g @earendil-works/pi-coding-agent@0.74.0";
|
|
@@ -8,4 +8,5 @@ export declare const models: Array<{
|
|
|
8
8
|
}>;
|
|
9
9
|
export declare const modelProfiles: AdapterModelProfileDefinition[];
|
|
10
10
|
export declare const agentConfigurationDoc = "# pi_local_serialized agent configuration\n\nAdapter: pi_local_serialized\n\nLike pi_local but enforces a global concurrency of 1 across all agents using this\nadapter within the same server process. Useful when running local LLMs that cannot\nhandle parallel inference load \u2014 runs are queued and executed one at a time.\n\nUse when:\n- You want Paperclip to run Pi (the AI coding agent) locally as the agent runtime\n- Your LLM backend cannot handle concurrent requests (e.g. local ollama, llama.cpp)\n- You want provider/model routing in Pi format (--provider <name> --model <id>)\n- You want Pi session resume across heartbeats via --session\n- You need Pi's tool set (read, bash, edit, write, grep, find, ls)\n\nDon't use when:\n- You need webhook-style external invocation (use openclaw_gateway or http)\n- You only need one-shot shell commands (use process)\n- Pi CLI is not installed on the machine\n- Your LLM backend supports concurrent requests (use pi_local instead)\n\nCore fields:\n- cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible)\n- instructionsFilePath (string, optional): absolute path to a markdown instructions file appended to system prompt via --append-system-prompt\n- promptTemplate (string, optional): user prompt template passed via -p flag\n- model (string, required): Pi model id in provider/model format (for example ollama/qwen2.5-coder)\n- thinking (string, optional): thinking level (off, minimal, low, medium, high, xhigh)\n- command (string, optional): defaults to \"pi\"\n- env (object, optional): KEY=VALUE environment variables\n\nOperational fields:\n- timeoutSec (number, optional): run timeout in seconds\n- graceSec (number, optional): SIGTERM grace period in seconds\n\nNotes:\n- Pi supports multiple providers and models. Use `pi --list-models` to list available options.\n- Paperclip requires an explicit `model` value for `pi_local_serialized` agents.\n- Sessions are stored in ~/.pi/paperclips/ and resumed with --session.\n- All tools (read, bash, edit, write, grep, find, ls) are enabled by default.\n- Agent instructions are appended to Pi's system prompt via --append-system-prompt, while the user task is sent via -p.\n- Concurrency is enforced in-process. If you run multiple Paperclip server replicas,\n each replica has its own queue \u2014 use a single replica when strict global serialization matters.\n";
|
|
11
|
+
export declare function createServerAdapter(): ServerAdapterModule;
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAUrG,eAAO,MAAM,IAAI,wBAAwB,CAAC;AAC1C,eAAO,MAAM,KAAK,2BAA2B,CAAC;AAE9C,eAAO,MAAM,uBAAuB,0DAA0D,CAAC;AAE/F,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAM,CAAC;AAE/D,eAAO,MAAM,aAAa,EAAE,6BAA6B,EAAO,CAAC;AAEjE,eAAO,MAAM,qBAAqB,84EA0CjC,CAAC;AAEF,wBAAgB,mBAAmB,IAAI,mBAAmB,CAazD"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execute, sessionCodec, listPiSkills, syncPiSkills, testEnvironment, listPiModels, } from "./server/index.js";
|
|
1
2
|
export const type = "pi_local_serialized";
|
|
2
3
|
export const label = "Pi (local, serialized)";
|
|
3
4
|
export const SANDBOX_INSTALL_COMMAND = "npm install -g @earendil-works/pi-coding-agent@0.74.0";
|
|
@@ -46,4 +47,18 @@ Notes:
|
|
|
46
47
|
- Concurrency is enforced in-process. If you run multiple Paperclip server replicas,
|
|
47
48
|
each replica has its own queue — use a single replica when strict global serialization matters.
|
|
48
49
|
`;
|
|
50
|
+
export function createServerAdapter() {
|
|
51
|
+
return {
|
|
52
|
+
type,
|
|
53
|
+
execute,
|
|
54
|
+
testEnvironment,
|
|
55
|
+
listSkills: listPiSkills,
|
|
56
|
+
syncSkills: syncPiSkills,
|
|
57
|
+
sessionCodec,
|
|
58
|
+
models,
|
|
59
|
+
modelProfiles,
|
|
60
|
+
listModels: listPiModels,
|
|
61
|
+
agentConfigurationDoc,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
49
64
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,IAAI,GAAG,qBAAqB,CAAC;AAC1C,MAAM,CAAC,MAAM,KAAK,GAAG,wBAAwB,CAAC;AAE9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,uDAAuD,CAAC;AAE/F,MAAM,CAAC,MAAM,MAAM,GAAyC,EAAE,CAAC;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAoC,EAAE,CAAC;AAEjE,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CpC,CAAC;AAEF,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,IAAI;QACJ,OAAO;QACP,eAAe;QACf,UAAU,EAAE,YAAY;QACxB,UAAU,EAAE,YAAY;QACxB,YAAY;QACZ,MAAM;QACN,aAAa;QACb,UAAU,EAAE,YAAY;QACxB,qBAAqB;KACtB,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/server/concurrency.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/server/concurrency.ts"],"names":[],"mappings":"AAgBA,wBAAsB,uBAAuB,CAAC,CAAC,EAC7C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACpE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAqCZ"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// Global mutex ensuring at most one pi_local_serialized execution runs at a time.
|
|
2
2
|
// Implemented as a promise chain — each caller appends to the tail and waits
|
|
3
3
|
// for the previous occupant to release before proceeding.
|
|
4
|
+
const HEARTBEAT_INTERVAL_MS = 30_000;
|
|
5
|
+
function formatWaitDuration(ms) {
|
|
6
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
7
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
8
|
+
const seconds = totalSeconds % 60;
|
|
9
|
+
if (minutes === 0)
|
|
10
|
+
return `${seconds}s`;
|
|
11
|
+
return `${minutes}m ${seconds}s`;
|
|
12
|
+
}
|
|
4
13
|
let tail = Promise.resolve();
|
|
5
14
|
export async function withSerializedExecution(label, onLog, fn) {
|
|
6
15
|
let release;
|
|
@@ -10,11 +19,26 @@ export async function withSerializedExecution(label, onLog, fn) {
|
|
|
10
19
|
// Snapshot the current tail and atomically replace it with our waiter.
|
|
11
20
|
const wait = tail;
|
|
12
21
|
tail = tail.then(() => next);
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
const isQueued = wait !== Promise.resolve();
|
|
23
|
+
if (isQueued) {
|
|
15
24
|
await onLog("stdout", `[paperclip] pi_local_serialized: another run is in progress, queuing "${label}"...\n`);
|
|
25
|
+
const waitStart = Date.now();
|
|
26
|
+
const heartbeat = setInterval(() => {
|
|
27
|
+
const elapsed = formatWaitDuration(Date.now() - waitStart);
|
|
28
|
+
onLog("stdout", `[paperclip] pi_local_serialized: "${label}" still waiting for the lock (${elapsed})...\n`).catch(() => undefined);
|
|
29
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
30
|
+
try {
|
|
31
|
+
await wait;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
clearInterval(heartbeat);
|
|
35
|
+
}
|
|
36
|
+
const totalWait = formatWaitDuration(Date.now() - waitStart);
|
|
37
|
+
await onLog("stdout", `[paperclip] pi_local_serialized: "${label}" acquired the lock after ${totalWait}, starting now.\n`);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
await wait;
|
|
16
41
|
}
|
|
17
|
-
await wait;
|
|
18
42
|
try {
|
|
19
43
|
return await fn();
|
|
20
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/server/concurrency.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,6EAA6E;AAC7E,0DAA0D;AAE1D,IAAI,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAa,EACb,KAAoE,EACpE,EAAoB;IAEpB,IAAI,OAAoB,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACzC,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,uEAAuE;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAE7B,
|
|
1
|
+
{"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/server/concurrency.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,6EAA6E;AAC7E,0DAA0D;AAE1D,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAErC,SAAS,kBAAkB,CAAC,EAAU;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,IAAI,OAAO,KAAK,CAAC;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACxC,OAAO,GAAG,OAAO,KAAK,OAAO,GAAG,CAAC;AACnC,CAAC;AAED,IAAI,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAa,EACb,KAAoE,EACpE,EAAoB;IAEpB,IAAI,OAAoB,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACzC,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,uEAAuE;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC;IAClB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAE7B,MAAM,QAAQ,GAAG,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,CAAC,QAAQ,EAAE,yEAAyE,KAAK,QAAQ,CAAC,CAAC;QAE9G,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;YAC3D,KAAK,CAAC,QAAQ,EAAE,qCAAqC,KAAK,iCAAiC,OAAO,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrI,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAE1B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,aAAa,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;QAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;QAC7D,MAAM,KAAK,CAAC,QAAQ,EAAE,qCAAqC,KAAK,6BAA6B,SAAS,mBAAmB,CAAC,CAAC;IAC7H,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,CAAC;IACb,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|