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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ dwctl/static/*
!dwctl/static/index.html
target/

# Generated email files (for testing)
dwctl/emails/

# Coverage reports
cobertura.xml
*.lcov
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,14 @@ batches:
# When disabled, these endpoints will not be available (default: true)
enabled: true

# Allowed completion windows (SLAs) for batch processing
# Allowed completion windows for batch processing
# These define the maximum time from batch creation to completion
# Default: ["24h"] - only 24 hour completion window is allowed
allowed_completion_windows:
- "24h"
- "1h"
# - "12h" # Uncomment to allow 12 hour SLA
# - "48h" # Uncomment to allow 48 hour SLA
# - "12h" # Uncomment to allow 12 hour
# - "48h" # Uncomment to allow 48 hour
Comment thread
pjb157 marked this conversation as resolved.

# Allowed OpenAI-compatible URL paths for batch requests.
# This is used by both /files upload validation and /batches endpoint validation.
Expand Down Expand Up @@ -327,7 +327,7 @@ background_services:
# All retry parameters are optional and default to fusillade's built-in defaults
# min_retries: 3 - Minimum retries guaranteed regardless of other limits
# max_retries: None - No cap on retries (only limited by deadline if set)
stop_before_deadline_ms: 0 # When to stop retrying/escalating relative to the batch SLA Deadline. Positive means before deadline, negative means after deadline (default: 0, stop on expiration deadline)
stop_before_deadline_ms: 0 # When to stop retrying/escalating relative to the batch completion window. Positive means before deadline, negative means after deadline (default: 0, stop on expiration deadline)

backoff_ms: 1000 # Initial backoff duration in milliseconds
backoff_factor: 2 # Exponential backoff multiplier
Expand Down
38 changes: 19 additions & 19 deletions dashboard/index.html
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="preload"
href="/src/assets/onwards-logo.svg"
as="image"
fetchpriority="high"
/>
<title>Doubleword Control Layer</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="preload"
href="/src/assets/onwards-logo.svg"
as="image"
fetchpriority="high"
/>
<title>Doubleword Control Layer</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>

<!-- Bootstrap is used for custom JS configured via deployment env -->
<!-- Look at control-layer/dwctl/src/api/handlers/static_assets.rs -->
<script src="/bootstrap.js"></script>
</body>
<!-- Bootstrap is used for custom JS configured via deployment env -->
<!-- Look at control-layer/dwctl/src/api/handlers/static_assets.rs -->
<script src="/bootstrap.js"></script>
</body>
</html>
27 changes: 3 additions & 24 deletions dashboard/public/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,7 @@ var bootstrapContent = `
.dw-bb *, .dw-bb *::before { box-sizing: border-box; }
.dw-bb p, .dw-bb h2, .dw-bb h3 { margin: 0; }
.dw-glow {
position: absolute;
border-radius: 9999px;
pointer-events: none;
}
.dw-glow--top {
top: 0; right: 0;
width: 16rem; height: 16rem;
background: ${colors.primaryLighter};
filter: blur(48px);
transform: translate(50%, -50%);
}
.dw-glow--bottom {
bottom: 0; left: 0;
width: 12rem; height: 12rem;
background: ${colors.primaryLight};
filter: blur(32px);
transform: translate(-25%, 50%);
display: none;
}
.dw-content {
position: relative;
Expand All @@ -61,13 +45,8 @@ var bootstrapContent = `
gap: 0.5rem;
}
.dw-dot {
display: inline-block;
width: 0.5rem; height: 0.5rem;
border-radius: 9999px;
background: ${colors.primary};
animation: dwP 2s ease-in-out infinite;
display: none;
}
@keyframes dwP { 0%,100%{opacity:1} 50%{opacity:.3} }
.dw-muted { color: ${colors.muted}; }
.dw-hl { color: ${colors.primary}; font-weight: 500; }
.dw-badges { display: flex; flex-wrap: wrap; gap: 0.75rem; }
Expand Down Expand Up @@ -171,7 +150,7 @@ var bootstrapContent = `
<div class="dw-badges">
<div class="dw-badge">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
<span>1h or 24h SLA</span>
<span>High or Standard Priority</span>
</div>
<div class="dw-badge">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/></svg>
Expand Down
38 changes: 16 additions & 22 deletions dashboard/src/api/control-layer/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ const fetchAiApi = (path: string, init?: RequestInit): Promise<Response> => {
// When making cross-origin requests, include credentials for session cookies
const options: RequestInit = {
...init,
credentials: aiApiBaseUrl
? "include"
: init?.credentials || "same-origin",
credentials: aiApiBaseUrl ? "include" : init?.credentials || "same-origin",
};
return fetch(url, options);
};
Expand Down Expand Up @@ -246,9 +244,7 @@ const userApi = {
// Nested webhooks under users
webhooks: {
async list(userId: string = "current"): Promise<Webhook[]> {
const response = await fetch(
`/admin/api/v1/users/${userId}/webhooks`,
);
const response = await fetch(`/admin/api/v1/users/${userId}/webhooks`);
if (!response.ok) {
throw new Error(`Failed to fetch webhooks: ${response.status}`);
}
Expand All @@ -259,14 +255,11 @@ const userApi = {
data: WebhookCreateRequest,
userId: string = "current",
): Promise<WebhookWithSecret> {
const response = await fetch(
`/admin/api/v1/users/${userId}/webhooks`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
},
);
const response = await fetch(`/admin/api/v1/users/${userId}/webhooks`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Failed to create webhook: ${response.status}`);
}
Expand All @@ -292,10 +285,7 @@ const userApi = {
return response.json();
},

async delete(
webhookId: string,
userId: string = "current",
): Promise<void> {
async delete(webhookId: string, userId: string = "current"): Promise<void> {
const response = await fetch(
`/admin/api/v1/users/${userId}/webhooks/${webhookId}`,
{
Expand All @@ -322,7 +312,6 @@ const userApi = {
}
return response.json();
},

},
};

Expand Down Expand Up @@ -394,7 +383,9 @@ const modelApi = {

if (!response.ok) {
const errorText = await response.text();
throw new Error(errorText || `Failed to create model: ${response.status}`);
throw new Error(
errorText || `Failed to create model: ${response.status}`,
);
}

return response.json();
Expand All @@ -403,7 +394,9 @@ const modelApi = {
// Composite model component operations
components: {
async list(modelId: string): Promise<ModelComponent[]> {
const response = await fetch(`/admin/api/v1/models/${modelId}/components`);
const response = await fetch(
`/admin/api/v1/models/${modelId}/components`,
);
if (!response.ok) {
throw new Error(`Failed to fetch model components: ${response.status}`);
}
Expand Down Expand Up @@ -1094,7 +1087,8 @@ const paymentsApi = {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(
errorData.message || `Failed to create billing portal session: ${response.status}`,
errorData.message ||
`Failed to create billing portal session: ${response.status}`,
);
}

Expand Down
1 change: 0 additions & 1 deletion dashboard/src/api/control-layer/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1352,4 +1352,3 @@ export function useRotateWebhookSecret() {
}) => dwctlApi.users.webhooks.rotateSecret(webhookId, userId),
});
}

3 changes: 1 addition & 2 deletions dashboard/src/api/control-layer/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ export const queryKeys = {
// Monitoring
monitoring: {
all: ["monitoring"] as const,
pendingRequestCounts: () =>
["monitoring", "pendingRequestCounts"] as const,
pendingRequestCounts: () => ["monitoring", "pendingRequestCounts"] as const,
},

// Files
Expand Down
Loading