chore: clean artifacts and fix device roles
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -35,6 +35,8 @@ vendor/
|
|||||||
apps/ios/Clawdbot.xcodeproj/
|
apps/ios/Clawdbot.xcodeproj/
|
||||||
apps/ios/Clawdbot.xcodeproj/**
|
apps/ios/Clawdbot.xcodeproj/**
|
||||||
apps/macos/.build/**
|
apps/macos/.build/**
|
||||||
|
**/*.bun-build
|
||||||
|
apps/ios/*.xcfilelist
|
||||||
|
|
||||||
# Vendor build artifacts
|
# Vendor build artifacts
|
||||||
vendor/a2ui/renderers/lit/dist/
|
vendor/a2ui/renderers/lit/dist/
|
||||||
@@ -48,6 +50,7 @@ apps/ios/fastlane/screenshots/
|
|||||||
apps/ios/fastlane/test_output/
|
apps/ios/fastlane/test_output/
|
||||||
apps/ios/fastlane/logs/
|
apps/ios/fastlane/logs/
|
||||||
apps/ios/fastlane/.env
|
apps/ios/fastlane/.env
|
||||||
|
apps/ios/fastlane/report.xml
|
||||||
|
|
||||||
# fastlane build artifacts (local)
|
# fastlane build artifacts (local)
|
||||||
apps/ios/*.ipa
|
apps/ios/*.ipa
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export const DevicePairRequestedEventSchema = Type.Object(
|
|||||||
clientId: Type.Optional(NonEmptyString),
|
clientId: Type.Optional(NonEmptyString),
|
||||||
clientMode: Type.Optional(NonEmptyString),
|
clientMode: Type.Optional(NonEmptyString),
|
||||||
role: Type.Optional(NonEmptyString),
|
role: Type.Optional(NonEmptyString),
|
||||||
|
roles: Type.Optional(Type.Array(NonEmptyString)),
|
||||||
scopes: Type.Optional(Type.Array(NonEmptyString)),
|
scopes: Type.Optional(Type.Array(NonEmptyString)),
|
||||||
remoteIp: Type.Optional(NonEmptyString),
|
remoteIp: Type.Optional(NonEmptyString),
|
||||||
silent: Type.Optional(Type.Boolean()),
|
silent: Type.Optional(Type.Boolean()),
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ import {
|
|||||||
} from "./nodes.helpers.js";
|
} from "./nodes.helpers.js";
|
||||||
import type { GatewayRequestHandlers } from "./types.js";
|
import type { GatewayRequestHandlers } from "./types.js";
|
||||||
|
|
||||||
|
function isNodeEntry(entry: { role?: string; roles?: string[] }) {
|
||||||
|
if (entry.role === "node") return true;
|
||||||
|
if (Array.isArray(entry.roles) && entry.roles.includes("node")) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
export const nodeHandlers: GatewayRequestHandlers = {
|
export const nodeHandlers: GatewayRequestHandlers = {
|
||||||
"node.pair.request": async ({ params, respond, context }) => {
|
"node.pair.request": async ({ params, respond, context }) => {
|
||||||
if (!validateNodePairRequestParams(params)) {
|
if (!validateNodePairRequestParams(params)) {
|
||||||
@@ -207,7 +213,7 @@ export const nodeHandlers: GatewayRequestHandlers = {
|
|||||||
const list = await listDevicePairing();
|
const list = await listDevicePairing();
|
||||||
const pairedById = new Map(
|
const pairedById = new Map(
|
||||||
list.paired
|
list.paired
|
||||||
.filter((entry) => entry.role === "node")
|
.filter((entry) => isNodeEntry(entry))
|
||||||
.map((entry) => [
|
.map((entry) => [
|
||||||
entry.deviceId,
|
entry.deviceId,
|
||||||
{
|
{
|
||||||
@@ -284,7 +290,7 @@ export const nodeHandlers: GatewayRequestHandlers = {
|
|||||||
}
|
}
|
||||||
await respondUnavailableOnThrow(respond, async () => {
|
await respondUnavailableOnThrow(respond, async () => {
|
||||||
const list = await listDevicePairing();
|
const list = await listDevicePairing();
|
||||||
const paired = list.paired.find((n) => n.deviceId === id && n.role === "node");
|
const paired = list.paired.find((n) => n.deviceId === id && isNodeEntry(n));
|
||||||
const connected = context.nodeRegistry.listConnected();
|
const connected = context.nodeRegistry.listConnected();
|
||||||
const live = connected.find((n) => n.nodeId === id);
|
const live = connected.find((n) => n.nodeId === id);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type DevicePairingPendingRequest = {
|
|||||||
clientId?: string;
|
clientId?: string;
|
||||||
clientMode?: string;
|
clientMode?: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
|
roles?: string[];
|
||||||
scopes?: string[];
|
scopes?: string[];
|
||||||
remoteIp?: string;
|
remoteIp?: string;
|
||||||
silent?: boolean;
|
silent?: boolean;
|
||||||
@@ -27,6 +28,7 @@ export type PairedDevice = {
|
|||||||
clientId?: string;
|
clientId?: string;
|
||||||
clientMode?: string;
|
clientMode?: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
|
roles?: string[];
|
||||||
scopes?: string[];
|
scopes?: string[];
|
||||||
remoteIp?: string;
|
remoteIp?: string;
|
||||||
createdAtMs: number;
|
createdAtMs: number;
|
||||||
@@ -134,6 +136,24 @@ function normalizeDeviceId(deviceId: string) {
|
|||||||
return deviceId.trim();
|
return deviceId.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mergeRoles(...items: Array<string | string[] | undefined>): string[] | undefined {
|
||||||
|
const roles = new Set<string>();
|
||||||
|
for (const item of items) {
|
||||||
|
if (!item) continue;
|
||||||
|
if (Array.isArray(item)) {
|
||||||
|
for (const role of item) {
|
||||||
|
const trimmed = role.trim();
|
||||||
|
if (trimmed) roles.add(trimmed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const trimmed = item.trim();
|
||||||
|
if (trimmed) roles.add(trimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (roles.size === 0) return undefined;
|
||||||
|
return [...roles];
|
||||||
|
}
|
||||||
|
|
||||||
export async function listDevicePairing(baseDir?: string): Promise<DevicePairingList> {
|
export async function listDevicePairing(baseDir?: string): Promise<DevicePairingList> {
|
||||||
const state = await loadState(baseDir);
|
const state = await loadState(baseDir);
|
||||||
const pending = Object.values(state.pendingById).sort((a, b) => b.ts - a.ts);
|
const pending = Object.values(state.pendingById).sort((a, b) => b.ts - a.ts);
|
||||||
@@ -179,6 +199,7 @@ export async function requestDevicePairing(
|
|||||||
clientId: req.clientId,
|
clientId: req.clientId,
|
||||||
clientMode: req.clientMode,
|
clientMode: req.clientMode,
|
||||||
role: req.role,
|
role: req.role,
|
||||||
|
roles: req.role ? [req.role] : undefined,
|
||||||
scopes: req.scopes,
|
scopes: req.scopes,
|
||||||
remoteIp: req.remoteIp,
|
remoteIp: req.remoteIp,
|
||||||
silent: req.silent,
|
silent: req.silent,
|
||||||
@@ -201,6 +222,7 @@ export async function approveDevicePairing(
|
|||||||
if (!pending) return null;
|
if (!pending) return null;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const existing = state.pairedByDeviceId[pending.deviceId];
|
const existing = state.pairedByDeviceId[pending.deviceId];
|
||||||
|
const roles = mergeRoles(existing?.roles, existing?.role, pending.roles, pending.role);
|
||||||
const device: PairedDevice = {
|
const device: PairedDevice = {
|
||||||
deviceId: pending.deviceId,
|
deviceId: pending.deviceId,
|
||||||
publicKey: pending.publicKey,
|
publicKey: pending.publicKey,
|
||||||
@@ -209,6 +231,7 @@ export async function approveDevicePairing(
|
|||||||
clientId: pending.clientId,
|
clientId: pending.clientId,
|
||||||
clientMode: pending.clientMode,
|
clientMode: pending.clientMode,
|
||||||
role: pending.role,
|
role: pending.role,
|
||||||
|
roles,
|
||||||
scopes: pending.scopes,
|
scopes: pending.scopes,
|
||||||
remoteIp: pending.remoteIp,
|
remoteIp: pending.remoteIp,
|
||||||
createdAtMs: existing?.createdAtMs ?? now,
|
createdAtMs: existing?.createdAtMs ?? now,
|
||||||
@@ -244,12 +267,15 @@ export async function updatePairedDeviceMetadata(
|
|||||||
const state = await loadState(baseDir);
|
const state = await loadState(baseDir);
|
||||||
const existing = state.pairedByDeviceId[normalizeDeviceId(deviceId)];
|
const existing = state.pairedByDeviceId[normalizeDeviceId(deviceId)];
|
||||||
if (!existing) return;
|
if (!existing) return;
|
||||||
|
const roles = mergeRoles(existing.roles, existing.role, patch.role);
|
||||||
state.pairedByDeviceId[deviceId] = {
|
state.pairedByDeviceId[deviceId] = {
|
||||||
...existing,
|
...existing,
|
||||||
...patch,
|
...patch,
|
||||||
deviceId: existing.deviceId,
|
deviceId: existing.deviceId,
|
||||||
createdAtMs: existing.createdAtMs,
|
createdAtMs: existing.createdAtMs,
|
||||||
approvedAtMs: existing.approvedAtMs,
|
approvedAtMs: existing.approvedAtMs,
|
||||||
|
role: patch.role ?? existing.role,
|
||||||
|
roles,
|
||||||
};
|
};
|
||||||
await persistState(state, baseDir);
|
await persistState(state, baseDir);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user