feat: add prek pre-commit hooks and dependabot (#1720)
* feat: add prek pre-commit hooks and dependabot Pre-commit hooks (via prek): - Basic hygiene: trailing-whitespace, end-of-file-fixer, check-yaml, check-added-large-files, check-merge-conflict - Security: detect-secrets, zizmor (GitHub Actions audit) - Linting: shellcheck, actionlint, oxlint, swiftlint - Formatting: oxfmt, swiftformat Dependabot: - npm and GitHub Actions ecosystems - Grouped updates (production/development/actions) - 7-day cooldown for supply chain protection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: add prek install instruction to AGENTS.md --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,2 @@
|
||||
import "./styles.css";
|
||||
import "./ui/app.ts";
|
||||
|
||||
|
||||
@@ -279,4 +279,3 @@
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,4 +122,3 @@
|
||||
border-top: 1px solid var(--border);
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,4 +196,3 @@
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,4 +3,3 @@ export type EventLogEntry = {
|
||||
event: string;
|
||||
payload?: unknown;
|
||||
};
|
||||
|
||||
|
||||
@@ -154,13 +154,13 @@ const COMPACTION_TOAST_DURATION_MS = 5000;
|
||||
export function handleCompactionEvent(host: CompactionHost, payload: AgentEventPayload) {
|
||||
const data = payload.data ?? {};
|
||||
const phase = typeof data.phase === "string" ? data.phase : "";
|
||||
|
||||
|
||||
// Clear any existing timer
|
||||
if (host.compactionClearTimer != null) {
|
||||
window.clearTimeout(host.compactionClearTimer);
|
||||
host.compactionClearTimer = null;
|
||||
}
|
||||
|
||||
|
||||
if (phase === "start") {
|
||||
host.compactionStatus = {
|
||||
active: true,
|
||||
@@ -183,13 +183,13 @@ export function handleCompactionEvent(host: CompactionHost, payload: AgentEventP
|
||||
|
||||
export function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPayload) {
|
||||
if (!payload) return;
|
||||
|
||||
|
||||
// Handle compaction events
|
||||
if (payload.stream === "compaction") {
|
||||
handleCompactionEvent(host as CompactionHost, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (payload.stream !== "tool") return;
|
||||
const sessionKey =
|
||||
typeof payload.sessionKey === "string" ? payload.sessionKey : undefined;
|
||||
|
||||
@@ -74,4 +74,3 @@ export function removePathValue(
|
||||
delete (current as Record<string, unknown>)[lastKey];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,4 +54,3 @@ export async function callDebugMethod(state: DebugState) {
|
||||
state.debugCallError = String(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,4 +33,3 @@ export async function loadPresence(state: PresenceState) {
|
||||
state.presenceLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,4 +39,3 @@ describe("stripThinkingTags", () => {
|
||||
expect(stripThinkingTags("Hello</final>")).toBe("Hello");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -30,4 +30,3 @@ describe("toSanitizedMarkdownHtml", () => {
|
||||
expect(html).toContain("console.log(1)");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -55,4 +55,3 @@ export function formatCronPayload(job: CronJob) {
|
||||
if (p.kind === "systemEvent") return `System: ${p.text}`;
|
||||
return `Agent: ${p.message}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,4 +30,3 @@ describe("generateUUID", () => {
|
||||
expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -40,4 +40,3 @@ export function generateUUID(cryptoLike: CryptoLike | null = globalThis.crypto):
|
||||
|
||||
return uuidFromBytes(weakRandomBytes());
|
||||
}
|
||||
|
||||
|
||||
@@ -43,4 +43,3 @@ export function renderChannelAccountCount(
|
||||
if (count < 2) return nothing;
|
||||
return html`<div class="account-count">Accounts (${count})</div>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,4 +116,3 @@ export function renderWhatsAppCard(params: {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ const COMPACTION_TOAST_DURATION_MS = 5000;
|
||||
|
||||
function renderCompactionIndicator(status: CompactionIndicatorStatus | null | undefined) {
|
||||
if (!status) return nothing;
|
||||
|
||||
|
||||
// Show "compacting..." while active
|
||||
if (status.active) {
|
||||
return html`
|
||||
@@ -91,7 +91,7 @@ function renderCompactionIndicator(status: CompactionIndicatorStatus | null | un
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nothing;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ export function renderNode(params: {
|
||||
const hasString = normalizedTypes.has("string");
|
||||
const hasNumber = normalizedTypes.has("number");
|
||||
const hasBoolean = normalizedTypes.has("boolean");
|
||||
|
||||
|
||||
if (hasBoolean && normalizedTypes.size === 1) {
|
||||
return renderNode({
|
||||
...params,
|
||||
@@ -383,14 +383,14 @@ function renderObject(params: {
|
||||
const hint = hintForPath(path, hints);
|
||||
const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));
|
||||
const help = hint?.help ?? schema.description;
|
||||
|
||||
|
||||
const fallback = value ?? schema.default;
|
||||
const obj = fallback && typeof fallback === "object" && !Array.isArray(fallback)
|
||||
? (fallback as Record<string, unknown>)
|
||||
: {};
|
||||
const props = schema.properties ?? {};
|
||||
const entries = Object.entries(props);
|
||||
|
||||
|
||||
// Sort by hint order
|
||||
const sorted = entries.sort((a, b) => {
|
||||
const orderA = hintForPath([...path, a[0]], hints)?.order ?? 0;
|
||||
@@ -514,7 +514,7 @@ function renderArray(params: {
|
||||
</button>
|
||||
</div>
|
||||
${help ? html`<div class="cfg-array__help">${help}</div>` : nothing}
|
||||
|
||||
|
||||
${arr.length === 0 ? html`
|
||||
<div class="cfg-array__empty">
|
||||
No items yet. Click "Add" to create one.
|
||||
@@ -597,7 +597,7 @@ function renderMapField(params: {
|
||||
Add Entry
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
${entries.length === 0 ? html`
|
||||
<div class="cfg-map__empty">No custom entries.</div>
|
||||
` : html`
|
||||
|
||||
@@ -94,16 +94,16 @@ function matchesSearch(key: string, schema: JsonSchema, query: string): boolean
|
||||
if (!query) return true;
|
||||
const q = query.toLowerCase();
|
||||
const meta = SECTION_META[key];
|
||||
|
||||
|
||||
// Check key name
|
||||
if (key.toLowerCase().includes(q)) return true;
|
||||
|
||||
|
||||
// Check label and description
|
||||
if (meta) {
|
||||
if (meta.label.toLowerCase().includes(q)) return true;
|
||||
if (meta.description.toLowerCase().includes(q)) return true;
|
||||
}
|
||||
|
||||
|
||||
return schemaMatches(schema, q);
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ export function renderConfigForm(props: ConfigFormProps) {
|
||||
<div class="config-empty">
|
||||
<div class="config-empty__icon">${icons.search}</div>
|
||||
<div class="config-empty__text">
|
||||
${searchQuery
|
||||
? `No settings match "${searchQuery}"`
|
||||
${searchQuery
|
||||
? `No settings match "${searchQuery}"`
|
||||
: "No settings in this section"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -89,4 +89,3 @@ export function isSensitivePath(path: Array<string | number>): boolean {
|
||||
key.endsWith("key")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,3 @@ export {
|
||||
} from "./config-form.analyze";
|
||||
export { renderNode } from "./config-form.node";
|
||||
export { schemaType, type JsonSchema } from "./config-form.shared";
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ function computeDiff(
|
||||
): Array<{ path: string; from: unknown; to: unknown }> {
|
||||
if (!original || !current) return [];
|
||||
const changes: Array<{ path: string; from: unknown; to: unknown }> = [];
|
||||
|
||||
|
||||
function compare(orig: unknown, curr: unknown, path: string) {
|
||||
if (orig === curr) return;
|
||||
if (typeof orig !== typeof curr) {
|
||||
@@ -164,7 +164,7 @@ function computeDiff(
|
||||
compare(origObj[key], currObj[key], path ? `${path}.${key}` : key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
compare(original, current, "");
|
||||
return changes;
|
||||
}
|
||||
@@ -258,7 +258,7 @@ export function renderConfig(props: ConfigProps) {
|
||||
<div class="config-sidebar__title">Settings</div>
|
||||
<span class="pill pill--sm ${validity === "valid" ? "pill--ok" : validity === "invalid" ? "pill--danger" : ""}">${validity}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Search -->
|
||||
<div class="config-search">
|
||||
<svg class="config-search__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -273,13 +273,13 @@ export function renderConfig(props: ConfigProps) {
|
||||
@input=${(e: Event) => props.onSearchChange((e.target as HTMLInputElement).value)}
|
||||
/>
|
||||
${props.searchQuery ? html`
|
||||
<button
|
||||
<button
|
||||
class="config-search__clear"
|
||||
@click=${() => props.onSearchChange("")}
|
||||
>×</button>
|
||||
` : nothing}
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Section nav -->
|
||||
<nav class="config-nav">
|
||||
<button
|
||||
@@ -299,7 +299,7 @@ export function renderConfig(props: ConfigProps) {
|
||||
</button>
|
||||
`)}
|
||||
</nav>
|
||||
|
||||
|
||||
<!-- Mode toggle at bottom -->
|
||||
<div class="config-sidebar__footer">
|
||||
<div class="config-mode-toggle">
|
||||
@@ -319,7 +319,7 @@ export function renderConfig(props: ConfigProps) {
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
||||
<!-- Main content -->
|
||||
<main class="config-main">
|
||||
<!-- Action bar -->
|
||||
@@ -358,7 +358,7 @@ export function renderConfig(props: ConfigProps) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Diff panel (form mode only - raw mode doesn't have granular diff) -->
|
||||
${hasChanges && props.formMode === "form" ? html`
|
||||
<details class="config-diff">
|
||||
|
||||
Reference in New Issue
Block a user