Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions apps/app/src/data/tools/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ export const findOrganization = tool({
});

if (!org) {
return { error: "Organization not found" };
return {
organization: null,
message: "Organization not found",
};
}

return org;
return {
organization: org,
};
},
});
22 changes: 20 additions & 2 deletions apps/app/src/data/tools/policies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,16 @@ export const getPolicies = tool({
},
});

return policies;
if (policies.length === 0) {
return {
policies: [],
message: "No policies found",
};
}

return {
policies,
};
},
});

Expand All @@ -61,6 +70,15 @@ export const getPolicyContent = tool({
},
});

return policy?.content;
if (!policy) {
return {
content: null,
message: "Policy not found",
};
}

return {
content: policy?.content,
};
},
});
22 changes: 20 additions & 2 deletions apps/app/src/data/tools/risks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ export const getRisks = tool({
},
});

return risks;
if (risks.length === 0) {
return {
risks: [],
message: "No risks found",
};
}

return {
risks,
};
},
});

Expand Down Expand Up @@ -119,6 +128,15 @@ export const getRiskById = tool({
},
});

return risk;
if (!risk) {
return {
risk: null,
message: "Risk not found",
};
}

return {
risk,
};
},
});
48 changes: 36 additions & 12 deletions apps/app/src/hooks/use-streamable-text.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,60 @@
import { type StreamableValue, readStreamableValue } from "ai/rsc";
import { useEffect, useState } from "react";
import { useEffect, useState, useCallback, useTransition } from "react";

export const useStreamableText = (
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);

useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);

return debouncedValue;
}

export function useStreamableText(
content: string | StreamableValue<string>,
) => {
debounceMs = 200,
): string {
const [rawContent, setRawContent] = useState(
typeof content === "string" ? content : "",
);
const [isPending, startTransition] = useTransition();
const debouncedContent = useDebounce(rawContent, debounceMs);

useEffect(() => {
if (typeof content === "string") {
setRawContent(content);
return;
}

let isMounted = true;
const controller = new AbortController();
const { signal } = controller;

(async () => {
let accumulated = "";
for await (const delta of readStreamableValue(content)) {
if (!isMounted) break;
if (typeof delta === "string") {
accumulated += delta;
setRawContent(accumulated);
try {
for await (const delta of readStreamableValue(content)) {
if (signal.aborted) break;
if (typeof delta === "string") {
accumulated += delta;
startTransition(() => {
setRawContent(accumulated);
});
}
}
} catch (error) {
if (error instanceof Error && error.name === "AbortError") {
return;
}
throw error;
}
})();

return () => {
isMounted = false;
controller.abort();
};
}, [content]);

return rawContent;
};
return debouncedContent;
}