@rosetears/aili-pi 0.1.0 → 0.1.1
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 +7 -1
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/extensions/header/index.ts +92 -0
- package/extensions/matrix/index.ts +375 -0
- package/extensions/zentui/config.ts +1014 -0
- package/extensions/zentui/extension-status.ts +96 -0
- package/extensions/zentui/fixed-editor/cluster.ts +98 -0
- package/extensions/zentui/fixed-editor/compositor.ts +719 -0
- package/extensions/zentui/fixed-editor/index.ts +223 -0
- package/extensions/zentui/fixed-editor/input.ts +85 -0
- package/extensions/zentui/fixed-editor/pi-compat.ts +296 -0
- package/extensions/zentui/fixed-editor/selection.ts +217 -0
- package/extensions/zentui/fixed-editor/terminal-modes.ts +75 -0
- package/extensions/zentui/fixed-editor/types.ts +37 -0
- package/extensions/zentui/footer-format.ts +279 -0
- package/extensions/zentui/footer.ts +595 -0
- package/extensions/zentui/format.ts +434 -0
- package/extensions/zentui/git.ts +384 -0
- package/extensions/zentui/gradient.ts +70 -0
- package/extensions/zentui/icons.ts +252 -0
- package/extensions/zentui/index.ts +577 -0
- package/extensions/zentui/live-context.ts +75 -0
- package/extensions/zentui/package-version.ts +650 -0
- package/extensions/zentui/project-refresh.ts +104 -0
- package/extensions/zentui/project-state.ts +59 -0
- package/extensions/zentui/prototype-patch-registry.ts +111 -0
- package/extensions/zentui/runtime.ts +841 -0
- package/extensions/zentui/selector-border.ts +77 -0
- package/extensions/zentui/session-lifecycle.ts +60 -0
- package/extensions/zentui/settings-command.ts +897 -0
- package/extensions/zentui/state.ts +55 -0
- package/extensions/zentui/style.ts +332 -0
- package/extensions/zentui/thinking-message.ts +159 -0
- package/extensions/zentui/tool-execution.ts +189 -0
- package/extensions/zentui/ui.ts +618 -0
- package/extensions/zentui/user-message.ts +252 -0
- package/licenses/pi-sakura-cyberdeck-MIT.txt +21 -0
- package/licenses/pi-zentui-MIT.txt +21 -0
- package/manifests/provenance.json +11 -0
- package/manifests/sbom.json +17 -1
- package/notices/pi-sakura-cyberdeck-NOTICE.txt +6 -0
- package/package.json +11 -2
- package/src/runtime/doctor.ts +1 -1
- package/src/runtime/registry.ts +1 -1
- package/src/runtime/rem-head.txt +38 -0
- package/themes/rem-cyberdeck.json +32 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export type StopProjectRefreshInterval = () => void;
|
|
2
|
+
|
|
3
|
+
export type ScheduleProjectRefreshOptions = {
|
|
4
|
+
force?: boolean;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type ProjectRefreshScheduler<T> = {
|
|
8
|
+
schedule: (target: T, options?: ScheduleProjectRefreshOptions) => void;
|
|
9
|
+
stop: () => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const PROJECT_REFRESH_THROTTLE_MS = 5_000;
|
|
13
|
+
|
|
14
|
+
export function startProjectRefreshInterval(
|
|
15
|
+
intervalMs: number,
|
|
16
|
+
refresh: () => void,
|
|
17
|
+
): StopProjectRefreshInterval {
|
|
18
|
+
if (intervalMs <= 0) return () => {};
|
|
19
|
+
|
|
20
|
+
const timer = setInterval(refresh, intervalMs);
|
|
21
|
+
timer.unref?.();
|
|
22
|
+
|
|
23
|
+
return () => clearInterval(timer);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createProjectRefreshScheduler<T>(
|
|
27
|
+
refresh: (target: T) => Promise<void>,
|
|
28
|
+
afterRefresh: () => void,
|
|
29
|
+
throttleMs = PROJECT_REFRESH_THROTTLE_MS,
|
|
30
|
+
): ProjectRefreshScheduler<T> {
|
|
31
|
+
let refreshInFlight = false;
|
|
32
|
+
let refreshPending = false;
|
|
33
|
+
let pendingTarget: T | undefined;
|
|
34
|
+
let delayedRefresh: ReturnType<typeof setTimeout> | undefined;
|
|
35
|
+
let lastRefreshStartedAt: number | undefined;
|
|
36
|
+
let generation = 0;
|
|
37
|
+
|
|
38
|
+
const clearDelayedRefresh = () => {
|
|
39
|
+
if (!delayedRefresh) return;
|
|
40
|
+
clearTimeout(delayedRefresh);
|
|
41
|
+
delayedRefresh = undefined;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const runRefresh = (target: T) => {
|
|
45
|
+
clearDelayedRefresh();
|
|
46
|
+
if (refreshInFlight) {
|
|
47
|
+
refreshPending = true;
|
|
48
|
+
pendingTarget = target;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const currentGeneration = generation;
|
|
53
|
+
refreshInFlight = true;
|
|
54
|
+
lastRefreshStartedAt = Date.now();
|
|
55
|
+
void refresh(target)
|
|
56
|
+
.catch(() => undefined)
|
|
57
|
+
.finally(() => {
|
|
58
|
+
if (currentGeneration !== generation) return;
|
|
59
|
+
refreshInFlight = false;
|
|
60
|
+
afterRefresh();
|
|
61
|
+
if (refreshPending) {
|
|
62
|
+
refreshPending = false;
|
|
63
|
+
const nextTarget = pendingTarget ?? target;
|
|
64
|
+
pendingTarget = undefined;
|
|
65
|
+
schedule(nextTarget);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const schedule = (target: T, options: ScheduleProjectRefreshOptions = {}) => {
|
|
71
|
+
if (options.force || throttleMs <= 0 || lastRefreshStartedAt === undefined) {
|
|
72
|
+
runRefresh(target);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const delayMs = Math.max(0, throttleMs - (Date.now() - lastRefreshStartedAt));
|
|
77
|
+
if (delayMs === 0) {
|
|
78
|
+
runRefresh(target);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
pendingTarget = target;
|
|
83
|
+
if (delayedRefresh) return;
|
|
84
|
+
delayedRefresh = setTimeout(() => {
|
|
85
|
+
delayedRefresh = undefined;
|
|
86
|
+
const nextTarget = pendingTarget ?? target;
|
|
87
|
+
pendingTarget = undefined;
|
|
88
|
+
runRefresh(nextTarget);
|
|
89
|
+
}, delayMs);
|
|
90
|
+
delayedRefresh.unref?.();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
schedule,
|
|
95
|
+
stop() {
|
|
96
|
+
generation += 1;
|
|
97
|
+
clearDelayedRefresh();
|
|
98
|
+
refreshInFlight = false;
|
|
99
|
+
refreshPending = false;
|
|
100
|
+
pendingTarget = undefined;
|
|
101
|
+
lastRefreshStartedAt = undefined;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { GitReadResult } from "./git.js";
|
|
2
|
+
import { emptyGitStatus } from "./git.js";
|
|
3
|
+
import type { PackageVersionReadResult } from "./package-version.js";
|
|
4
|
+
import type { RuntimeReadResult } from "./runtime.js";
|
|
5
|
+
import type { FooterState } from "./state.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Apply a project refresh (git + runtime) onto footer state, preserving
|
|
9
|
+
* last-good values on transient errors and clearing on cwd change / not-a-repo.
|
|
10
|
+
*
|
|
11
|
+
* Returns the cwd to store as `previousCwd` for the next refresh.
|
|
12
|
+
*/
|
|
13
|
+
export function applyProjectRefreshToState(
|
|
14
|
+
state: FooterState,
|
|
15
|
+
args: {
|
|
16
|
+
cwd: string;
|
|
17
|
+
previousCwd: string | undefined;
|
|
18
|
+
git: GitReadResult;
|
|
19
|
+
runtime: RuntimeReadResult;
|
|
20
|
+
packageVersion?: PackageVersionReadResult;
|
|
21
|
+
},
|
|
22
|
+
): string {
|
|
23
|
+
const cwdChanged = args.previousCwd !== undefined && args.previousCwd !== args.cwd;
|
|
24
|
+
|
|
25
|
+
if (cwdChanged) {
|
|
26
|
+
Object.assign(state, emptyGitStatus());
|
|
27
|
+
state.runtime = undefined;
|
|
28
|
+
state.packageVersion = undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (args.git.kind === "ok") {
|
|
32
|
+
Object.assign(state, args.git.status);
|
|
33
|
+
} else if (args.git.kind === "not_a_repo") {
|
|
34
|
+
Object.assign(state, emptyGitStatus());
|
|
35
|
+
}
|
|
36
|
+
// kind === "error": keep previous git fields (unless cwdChanged already cleared)
|
|
37
|
+
|
|
38
|
+
if (args.runtime.kind === "ok") {
|
|
39
|
+
state.runtime = args.runtime.runtime;
|
|
40
|
+
} else if (cwdChanged && args.runtime.kind === "error") {
|
|
41
|
+
// Already cleared above; keep undefined.
|
|
42
|
+
state.runtime = undefined;
|
|
43
|
+
}
|
|
44
|
+
// error + same cwd: keep previous runtime
|
|
45
|
+
|
|
46
|
+
if (args.packageVersion !== undefined) {
|
|
47
|
+
if (args.packageVersion.kind === "ok") {
|
|
48
|
+
// `null` means "no manifest in this cwd"; clear so the segment disappears
|
|
49
|
+
// even on the same cwd when the user removes their manifest.
|
|
50
|
+
state.packageVersion = args.packageVersion.result ?? undefined;
|
|
51
|
+
} else if (!cwdChanged) {
|
|
52
|
+
// error + same cwd: keep previous packageVersion (last-good semantics)
|
|
53
|
+
} else {
|
|
54
|
+
state.packageVersion = undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return args.cwd;
|
|
59
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
export const ZENTUI_PROTOTYPE_PATCH_REGISTRY = Symbol.for("pi-zentui.prototype-patch-registry");
|
|
2
|
+
|
|
3
|
+
type PrototypePatchAdapter =
|
|
4
|
+
| "user-message-render"
|
|
5
|
+
| "user-message-invalidate"
|
|
6
|
+
| "selector-border-render"
|
|
7
|
+
| "tool-execution-render"
|
|
8
|
+
| "tool-execution-invalidate"
|
|
9
|
+
| "assistant-thinking-content";
|
|
10
|
+
|
|
11
|
+
type PrototypeMethodName = "render" | "invalidate" | "updateContent";
|
|
12
|
+
type PrototypeMethod = (this: unknown, ...args: unknown[]) => unknown;
|
|
13
|
+
|
|
14
|
+
type PatchInvocation = {
|
|
15
|
+
predecessor: PrototypeMethod;
|
|
16
|
+
receiver: unknown;
|
|
17
|
+
args: unknown[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type PatchBehavior = (invocation: PatchInvocation) => unknown;
|
|
21
|
+
|
|
22
|
+
type Registration = {
|
|
23
|
+
token: symbol;
|
|
24
|
+
behavior?: PatchBehavior;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type PatchRecord = {
|
|
28
|
+
method: PrototypeMethodName;
|
|
29
|
+
predecessor: PrototypeMethod;
|
|
30
|
+
wrapper: PrototypeMethod;
|
|
31
|
+
registration?: Registration;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type PatchRegistry = Map<PrototypePatchAdapter, PatchRecord>;
|
|
35
|
+
|
|
36
|
+
type PatchTarget = Record<PropertyKey, unknown>;
|
|
37
|
+
|
|
38
|
+
function registryFor(target: PatchTarget): PatchRegistry {
|
|
39
|
+
const existing = target[ZENTUI_PROTOTYPE_PATCH_REGISTRY];
|
|
40
|
+
if (existing instanceof Map) return existing as PatchRegistry;
|
|
41
|
+
const registry: PatchRegistry = new Map();
|
|
42
|
+
Object.defineProperty(target, ZENTUI_PROTOTYPE_PATCH_REGISTRY, {
|
|
43
|
+
value: registry,
|
|
44
|
+
configurable: true,
|
|
45
|
+
});
|
|
46
|
+
return registry;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function createCleanup(
|
|
50
|
+
target: PatchTarget,
|
|
51
|
+
method: PrototypeMethodName,
|
|
52
|
+
adapter: PrototypePatchAdapter,
|
|
53
|
+
registry: PatchRegistry,
|
|
54
|
+
record: PatchRecord,
|
|
55
|
+
token: symbol,
|
|
56
|
+
): () => void {
|
|
57
|
+
let cleaned = false;
|
|
58
|
+
return () => {
|
|
59
|
+
if (cleaned) return;
|
|
60
|
+
cleaned = true;
|
|
61
|
+
if (record.registration?.token !== token) return;
|
|
62
|
+
record.registration.behavior = undefined;
|
|
63
|
+
record.registration = undefined;
|
|
64
|
+
|
|
65
|
+
const current = registry.get(adapter);
|
|
66
|
+
if (current !== record) return;
|
|
67
|
+
if (target[method] === record.wrapper) target[method] = record.predecessor;
|
|
68
|
+
registry.delete(adapter);
|
|
69
|
+
if (registry.size === 0) delete target[ZENTUI_PROTOTYPE_PATCH_REGISTRY];
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function installPrototypePatch(
|
|
74
|
+
targetValue: object,
|
|
75
|
+
method: PrototypeMethodName,
|
|
76
|
+
adapter: PrototypePatchAdapter,
|
|
77
|
+
behavior: PatchBehavior,
|
|
78
|
+
): () => void {
|
|
79
|
+
const target = targetValue as PatchTarget;
|
|
80
|
+
const registry = registryFor(target);
|
|
81
|
+
let record = registry.get(adapter);
|
|
82
|
+
|
|
83
|
+
if (!(record && record.method === method && target[method] === record.wrapper)) {
|
|
84
|
+
const predecessor = target[method];
|
|
85
|
+
if (typeof predecessor !== "function") {
|
|
86
|
+
throw new TypeError(`Cannot patch ${method}: predecessor is not a function`);
|
|
87
|
+
}
|
|
88
|
+
const nextRecord: PatchRecord = {
|
|
89
|
+
method,
|
|
90
|
+
predecessor: predecessor as PrototypeMethod,
|
|
91
|
+
wrapper: () => undefined,
|
|
92
|
+
};
|
|
93
|
+
const wrapper: PrototypeMethod = function zentuiPrototypeWrapper(
|
|
94
|
+
this: unknown,
|
|
95
|
+
...args: unknown[]
|
|
96
|
+
): unknown {
|
|
97
|
+
const activeBehavior = nextRecord.registration?.behavior;
|
|
98
|
+
return activeBehavior
|
|
99
|
+
? activeBehavior({ predecessor: nextRecord.predecessor, receiver: this, args })
|
|
100
|
+
: Reflect.apply(nextRecord.predecessor, this, args);
|
|
101
|
+
};
|
|
102
|
+
nextRecord.wrapper = wrapper;
|
|
103
|
+
record = nextRecord;
|
|
104
|
+
registry.set(adapter, record);
|
|
105
|
+
target[method] = wrapper;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const token = Symbol(adapter);
|
|
109
|
+
record.registration = { token, behavior };
|
|
110
|
+
return createCleanup(target, method, adapter, registry, record, token);
|
|
111
|
+
}
|