chore: fork @llblab/[email protected].0 as @evandrodevbr/oh-my-pi-telegram
Fork of upstream llblab/[email protected].0 (SHA afe09c5) repackaged as a drop-in extension for can1357/oh-my-pi (omp >= 16.5.2). Changes vs upstream: - Rename package: @llblab/pi-telegram -> @evandrodevbr/oh-my-pi-telegram - Bump version: 0.22.0 -> 0.22.0-evandro.1 - Update repository/homepage/bugs URLs to evandrodevbr - Add omp field in package.json (displayName + compatibleWith) - README: prepend 'Oh My Pi (omp) Compatibility' section with install commands, verified-components table, upstream lineage, and rationale - CHANGELOG: add '0.22.0-evandro.1' entry under Unreleased - docs/: rename @llblab/pi-telegram imports to @evandrodevbr/oh-my-pi-telegram - tests/public-api.test.ts: rename package import paths Gates re-run on the fork: - npm run typecheck -> tsc --noEmit (success) - npm test -> 1229 pass / 0 fail / 1 platform-only skip - npm run audit -> found 0 vulnerabilities - npm run pack:check -> evandrodevbr-oh-my-pi-telegram-0.22.0-evandro.1.tgz Verified: - omp install --link ./pi-telegram -> Linked OK - omp plugin list -> @evandrodevbr/[email protected].0-evandro.1 Upstream lineage: badlogic/pi-telegram -> llblab/pi-telegram (0.22.0) -> evandrodevbr/oh-my-pi-telegram (this fork)
This commit is contained in:
commit
d1d04001d0
155 files changed
+107848
No files matched your search
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Regression tests for the pi SDK adapter boundary
|
||||
* Covers narrow bridge-facing helpers over concrete pi context contracts
|
||||
*/
|
||||
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
canStartPollingInExtensionContext,
|
||||
compactExtensionContext,
|
||||
createExtensionApiRuntimePorts,
|
||||
createScopedModelPatternPersister,
|
||||
type ExtensionContext,
|
||||
getExtensionContextCwd,
|
||||
formatPollingStartBlockedByRunMode,
|
||||
getExtensionContextMode,
|
||||
getExtensionContextModel,
|
||||
hasExtensionContextPendingMessages,
|
||||
isExtensionContextIdle,
|
||||
isExtensionContextPassiveRunMode,
|
||||
} from "../lib/pi.ts";
|
||||
|
||||
type PiRuntimeApiHarness = Parameters<
|
||||
typeof createExtensionApiRuntimePorts
|
||||
>[0] & {
|
||||
events: string[];
|
||||
};
|
||||
|
||||
type PiRuntimeModel = Parameters<PiRuntimeApiHarness["setModel"]>[0];
|
||||
|
||||
function createHarnessModel(id: string): PiRuntimeModel {
|
||||
return { id } as PiRuntimeModel;
|
||||
}
|
||||
|
||||
function getHarnessModelId(model: PiRuntimeModel): string {
|
||||
return String(Reflect.get(Object(model), "id"));
|
||||
}
|
||||
|
||||
test("Pi context mode helpers feature-detect passive run modes", () => {
|
||||
assert.equal(getExtensionContextMode({ mode: "print" }), "print");
|
||||
assert.equal(getExtensionContextMode({ mode: "bogus" }), undefined);
|
||||
assert.equal(isExtensionContextPassiveRunMode({ mode: "print" }), true);
|
||||
assert.equal(isExtensionContextPassiveRunMode({ mode: "json" }), true);
|
||||
assert.equal(isExtensionContextPassiveRunMode({ mode: "rpc" }), false);
|
||||
assert.equal(isExtensionContextPassiveRunMode({}), false);
|
||||
assert.equal(canStartPollingInExtensionContext({ mode: "tui" }), true);
|
||||
assert.equal(canStartPollingInExtensionContext({ mode: "rpc" }), true);
|
||||
assert.equal(canStartPollingInExtensionContext({ mode: "json" }), false);
|
||||
assert.equal(canStartPollingInExtensionContext({ mode: "print" }), false);
|
||||
assert.equal(canStartPollingInExtensionContext({}), true);
|
||||
assert.equal(
|
||||
formatPollingStartBlockedByRunMode({ mode: "json" }),
|
||||
"Telegram polling is unavailable in Pi json mode. Use /telegram-connect from a long-lived Pi session.",
|
||||
);
|
||||
});
|
||||
|
||||
test("Pi API runtime ports bind methods without losing receiver context", async () => {
|
||||
const api: PiRuntimeApiHarness = {
|
||||
events: [],
|
||||
sendUserMessage(content, options) {
|
||||
this.events.push(
|
||||
`send:${String(content)}:${options?.deliverAs ?? "default"}`,
|
||||
);
|
||||
},
|
||||
async exec(command, args) {
|
||||
this.events.push(`exec:${command}:${args.join(",")}`);
|
||||
return { stdout: "ok", stderr: "", code: 0, killed: false };
|
||||
},
|
||||
getCommands() {
|
||||
this.events.push("commands");
|
||||
return [];
|
||||
},
|
||||
getThinkingLevel() {
|
||||
this.events.push("get-thinking");
|
||||
return "high";
|
||||
},
|
||||
setThinkingLevel(level) {
|
||||
this.events.push(`thinking:${String(level)}`);
|
||||
},
|
||||
async setModel(model) {
|
||||
this.events.push(`model:${getHarnessModelId(model)}`);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
const runtime = createExtensionApiRuntimePorts(api);
|
||||
runtime.sendUserMessage("hello", { deliverAs: "followUp" });
|
||||
assert.deepEqual(await runtime.exec("cmd", ["arg"]), {
|
||||
stdout: "ok",
|
||||
stderr: "",
|
||||
code: 0,
|
||||
killed: false,
|
||||
});
|
||||
assert.deepEqual(runtime.getCommands(), []);
|
||||
assert.equal(runtime.getThinkingLevel(), "high");
|
||||
runtime.setThinkingLevel("low");
|
||||
assert.equal(await runtime.setModel(createHarnessModel("gpt-5")), true);
|
||||
assert.deepEqual(api.events, [
|
||||
"send:hello:followUp",
|
||||
"exec:cmd:arg",
|
||||
"commands",
|
||||
"get-thinking",
|
||||
"thinking:low",
|
||||
"model:gpt-5",
|
||||
]);
|
||||
});
|
||||
|
||||
test("Pi scoped model persister invalidates cached inputs without clearing live menus", async () => {
|
||||
const events: string[] = [];
|
||||
const persist = createScopedModelPatternPersister({
|
||||
createSettingsManager: (cwd) => ({
|
||||
reload: async () => {},
|
||||
flush: async () => {
|
||||
events.push("flush");
|
||||
},
|
||||
getEnabledModels: () => undefined,
|
||||
setEnabledModels: (patterns) => {
|
||||
events.push(`set:${cwd}:${patterns?.join(",") ?? "all"}`);
|
||||
},
|
||||
}),
|
||||
clearCachedModelMenuInputs: () => {
|
||||
events.push("clear-cache");
|
||||
},
|
||||
});
|
||||
await persist(["openai/gpt-5"], { cwd: "/tmp/project" } as ExtensionContext);
|
||||
assert.deepEqual(events, [
|
||||
"set:/tmp/project:openai/gpt-5",
|
||||
"flush",
|
||||
"clear-cache",
|
||||
]);
|
||||
});
|
||||
|
||||
test("Pi context helpers expose model, idle, pending-message, and compact adapters", () => {
|
||||
const model = { provider: "openai", id: "gpt-5", name: "GPT-5" };
|
||||
const events: string[] = [];
|
||||
const ctx = {
|
||||
model,
|
||||
isIdle: () => true,
|
||||
hasPendingMessages: () => false,
|
||||
cwd: "/tmp/project",
|
||||
compact: (callbacks: { onComplete: () => void }) => {
|
||||
events.push("compact");
|
||||
callbacks.onComplete();
|
||||
},
|
||||
} as unknown as ExtensionContext;
|
||||
compactExtensionContext(ctx, {
|
||||
onComplete: () => {
|
||||
events.push("complete");
|
||||
},
|
||||
onError: () => {
|
||||
events.push("error");
|
||||
},
|
||||
});
|
||||
assert.equal(getExtensionContextModel(ctx), model);
|
||||
assert.equal(getExtensionContextCwd(ctx), "/tmp/project");
|
||||
assert.equal(isExtensionContextIdle(ctx), true);
|
||||
assert.equal(hasExtensionContextPendingMessages(ctx), false);
|
||||
assert.deepEqual(events, ["compact", "complete"]);
|
||||
});
|
||||
Reference in new issue
Block a user