mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-30 05:02:58 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15635531c6 | ||
|
|
b678e122d5 |
@@ -1,3 +1,4 @@
|
||||
const withAndroidOrientation = require("./plugins/with-android-orientation");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const pkg = require("./package.json");
|
||||
@@ -142,6 +143,7 @@ export default {
|
||||
searchPaths: ["../../node_modules", "./node_modules"],
|
||||
},
|
||||
plugins: [
|
||||
withAndroidOrientation,
|
||||
"expo-router",
|
||||
withPasteInput,
|
||||
withAndroidScroll,
|
||||
|
||||
@@ -59,3 +59,31 @@ describe("Android app config", () => {
|
||||
30_000,
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps the Android manifest portrait for phone startup", async () => {
|
||||
const manifest = await resolveAndroidManifest();
|
||||
const activity = manifest.application[0].activity.find(
|
||||
(entry: ManifestEntry) => entry.$["android:name"] === ".MainActivity",
|
||||
);
|
||||
expect(activity.$["android:screenOrientation"]).toBe("portrait");
|
||||
}, 30_000);
|
||||
|
||||
it("updates the native orientation before launch and when screen size changes", async () => {
|
||||
const plugin = createRequire(import.meta.url)("./plugins/with-android-orientation.js");
|
||||
const config = plugin({ name: "test", slug: "test" });
|
||||
const result = await config.mods.android.mainActivity({
|
||||
modRequest: {},
|
||||
modResults: {
|
||||
language: "kt",
|
||||
contents:
|
||||
"class MainActivity {\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(null)\n }\n}",
|
||||
},
|
||||
});
|
||||
expect(result.modResults.contents).toContain("smallestScreenWidthDp >= 600");
|
||||
expect(result.modResults.contents).toContain("SCREEN_ORIENTATION_UNSPECIFIED");
|
||||
expect(result.modResults.contents).toContain("SCREEN_ORIENTATION_PORTRAIT");
|
||||
expect(result.modResults.contents).toContain(
|
||||
"updateOrientation(resources.configuration)\n super.onCreate(null)",
|
||||
);
|
||||
expect(result.modResults.contents).toContain("updateOrientation(newConfig)");
|
||||
});
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
const { withMainActivity } = require("expo/config-plugins");
|
||||
|
||||
module.exports = function withAndroidOrientation(config) {
|
||||
return withMainActivity(config, (mod) => {
|
||||
const activity = mod.modResults;
|
||||
if (activity.language !== "kt") throw new Error("Expected Kotlin MainActivity");
|
||||
const marker = " // Paseo orientation policy";
|
||||
if (!activity.contents.includes(marker)) {
|
||||
const anchor = " override fun onCreate(savedInstanceState: Bundle?)";
|
||||
if (!activity.contents.includes(anchor)) throw new Error("MainActivity anchor missing");
|
||||
activity.contents = activity.contents.replace(
|
||||
anchor,
|
||||
`${marker}
|
||||
private fun updateOrientation(configuration: android.content.res.Configuration) {
|
||||
val orientation = if (configuration.smallestScreenWidthDp >= 600)
|
||||
android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
else
|
||||
android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
if (requestedOrientation != orientation) requestedOrientation = orientation
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: android.content.res.Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
updateOrientation(newConfig)
|
||||
}
|
||||
|
||||
${anchor}`,
|
||||
);
|
||||
if (!activity.contents.includes(" super.onCreate(null)"))
|
||||
throw new Error("MainActivity onCreate missing");
|
||||
activity.contents = activity.contents.replace(
|
||||
" super.onCreate(null)",
|
||||
" updateOrientation(resources.configuration)\n super.onCreate(null)",
|
||||
);
|
||||
}
|
||||
return mod;
|
||||
});
|
||||
};
|
||||
@@ -1075,29 +1075,23 @@ export default function contribute(plugin: unknown) {
|
||||
const service = bindTestSessionHost(
|
||||
new PluginService(pino({ level: "silent" }), store, "0.4.0"),
|
||||
);
|
||||
try {
|
||||
await service.start();
|
||||
await service.installDirectory({ path: first });
|
||||
await service.installDirectory({ path: second });
|
||||
expect(catalogIds(service)).toEqual(["first", "second"]);
|
||||
await store.patch({ pluginsEnabled: false });
|
||||
await service.start();
|
||||
await service.installDirectory({ path: first });
|
||||
await service.installDirectory({ path: second });
|
||||
|
||||
expect(service.catalog()).toEqual([]);
|
||||
await expect(service.invokePluginRpc("second", "anything", {})).rejects.toThrow(
|
||||
"Plugin is not available",
|
||||
);
|
||||
await store.patch({ pluginsEnabled: true });
|
||||
// Observe recovery itself. Reloading here restarts a healthy plugin and
|
||||
// would also conceal a failure to restart it after the global enable.
|
||||
await expect
|
||||
.poll(() => service.listPlugins(), { timeout: 10_000 })
|
||||
.toMatchObject([
|
||||
{ id: "first", status: "running" },
|
||||
{ id: "second", status: "running" },
|
||||
]);
|
||||
} finally {
|
||||
await service.stopAllPlugins();
|
||||
}
|
||||
await store.patch({ pluginsEnabled: false });
|
||||
|
||||
expect(service.catalog()).toEqual([]);
|
||||
await expect(service.invokePluginRpc("second", "anything", {})).rejects.toThrow(
|
||||
"Plugin is not available",
|
||||
);
|
||||
await store.patch({ pluginsEnabled: true });
|
||||
await service.reloadPlugin("first");
|
||||
expect((await service.listPlugins()).map(({ id, status }) => ({ id, status }))).toEqual([
|
||||
{ id: "first", status: "running" },
|
||||
{ id: "second", status: "running" },
|
||||
]);
|
||||
await service.stopAllPlugins();
|
||||
}, 20_000);
|
||||
|
||||
it("does not publish an in-flight start after a later global disable", async () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ argument-hint: "[--profile <name>] <question or topic>"
|
||||
|
||||
Single agent. Reads the situation you're in. Gives a judgment. You decide what to do — the advisor doesn't drive the work.
|
||||
|
||||
Use the user's request and current conversation as input, including any arguments supplied with the skill invocation. Optional syntax: `[--profile <name>] <question or topic>`.
|
||||
**User's request:** $ARGUMENTS
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -40,15 +40,13 @@ This is analysis only. Do NOT edit, create, or delete any files. Do NOT write co
|
||||
|
||||
## Forwarded skills
|
||||
|
||||
If the user's request contains another skill reference, such as `/unslop`, `/skill:unslop`, or `$unslop`, the user is asking the advisor to run that skill against the current task. Examples:
|
||||
If `$ARGUMENTS` contains another skill reference — `/unslop`, `/unslop-risk`, `$unslop`, etc. — the user is asking the advisor to run that skill against the current task. Examples:
|
||||
|
||||
- `/paseo-advisor /unslop` → advisor runs `/unslop` on the current diff.
|
||||
- `/paseo-advisor /unslop-risk` → advisor does an unslop-risk review.
|
||||
- `/paseo-advisor $diagnose this build failure` → advisor invokes `/diagnose`.
|
||||
- `/skill:paseo-advisor /skill:unslop` → advisor runs the `unslop` skill on the current diff in Pi.
|
||||
- `$paseo-advisor $unslop` → advisor runs the `unslop` skill on the current diff in Codex.
|
||||
|
||||
Parse the forwarded skill name from the user's request (`/<name>`, `/skill:<name>`, or `$<name>`), excluding this skill's own invocation. In the briefing, tell the advisor explicitly:
|
||||
Parse the forwarded skill name out of `$ARGUMENTS` (`/<name>` or `$<name>`). In the briefing, tell the advisor explicitly:
|
||||
|
||||
```
|
||||
Invoke the `<name>` skill against this task. Load it via the Skill tool before doing anything else.
|
||||
|
||||
@@ -8,7 +8,7 @@ user-invocable: true
|
||||
|
||||
Two agents from contrasting profiles, fresh context, planning a solution in parallel.
|
||||
|
||||
Use the user's request and current conversation as input, including any arguments supplied with the skill invocation.
|
||||
**User's additional context:** $ARGUMENTS
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ user-invocable: true
|
||||
|
||||
Transfer the current task — context, decisions, failed attempts, constraints — to a fresh agent. The receiving agent starts with **zero context**, so the handoff prompt must be a self-contained briefing.
|
||||
|
||||
Use the user's request and current conversation as input, including any arguments supplied with the skill invocation.
|
||||
**User's arguments:** $ARGUMENTS
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ description: Answer questions about the Paseo product and app, including setup,
|
||||
|
||||
You are helping a user understand, configure, or troubleshoot Paseo itself. Answer their question directly, verify the answer against the current public documentation, and include the relevant documentation link. Do not send the user away to read the docs in place of helping them.
|
||||
|
||||
Use the user's question and current conversation as input, including any arguments supplied with the skill invocation.
|
||||
**User's question:** $ARGUMENTS
|
||||
|
||||
## Use current documentation
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ description: Build and manage trusted local Paseo plugins. Use when the user ask
|
||||
|
||||
Build or manage the requested plugin directly. Use the current public docs to catch contract changes, but keep working from this skill if the network is unavailable.
|
||||
|
||||
Use the user's request and current conversation as input, including any arguments supplied with the skill invocation.
|
||||
**User's request:** $ARGUMENTS
|
||||
|
||||
## Check current documentation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user