Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class LimitsSettingsStore: ObservableObject {
static let shared = LimitsSettingsStore(userDefaults: .standard)

/// All known provider identifiers, in default display order.
static let allProviders: [String] = ["claude", "codex", "cursor", "gemini", "kimi", "kiro", "grok", "copilot", "antigravity", "zcode", "opencodeGo", "qoder", "qoderCn"]
static let allProviders: [String] = ["claude", "codex", "cursor", "gemini", "kimi", "kiro", "grok", "copilot", "antigravity", "zcode", "opencodeGo", "qoder", "qoderCn", "codingPlan"]

static let displayNames: [String: String] = [
"claude": "Claude",
Expand All @@ -51,6 +51,7 @@ final class LimitsSettingsStore: ObservableObject {
"opencodeGo": "OpenCode Go",
"qoder": "Qoder",
"qoderCn": "Qoder CN",
"codingPlan": "Ark Coding Plan",
]

static let iconNames: [String: String] = [
Expand Down
14 changes: 14 additions & 0 deletions dashboard/public/brand-logos/volcano-ark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions dashboard/src/content/copy.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1469,3 +1469,17 @@ landing.v3.how.scene.files_changed,landing,LandingPage,HowItWorksSection,scene_f
landing.v3.how.scene.session_title,landing,LandingPage,HowItWorksSection,scene_session_title,"session log · last turn",,active
landing.v3.how.scene.appended,landing,LandingPage,HowItWorksSection,scene_appended,"appended locally",,active
landing.v3.how.scene.total_tokens,landing,LandingPage,HowItWorksSection,scene_total_tokens,"total tokens",,active
limits.provider.ark_coding_plan,ui,LimitsPage,UsageLimitsPanel,provider_ark_coding_plan,"Ark Coding Plan",,active
limits.label.ark_coding_plan_5h,ui,LimitsPage,UsageLimitsPanel,ark_coding_plan_5h,"5h",,active
limits.label.ark_coding_plan_weekly,ui,LimitsPage,UsageLimitsPanel,ark_coding_plan_weekly,"Weekly",,active
limits.label.ark_coding_plan_monthly,ui,LimitsPage,UsageLimitsPanel,ark_coding_plan_monthly,"Monthly",,active
limits.codingPlan.setupHint.title,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_title,"Connect Ark Coding Plan",,active
limits.codingPlan.setupHint.subtitle,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_subtitle,"Quota is read from the official Ark CLI (arkcli) on this machine.",,active
limits.codingPlan.setupHint.step1,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_step1,"Install the Ark CLI from npm.",,active
limits.codingPlan.setupHint.cta,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_cta,"View install guide",,active
limits.codingPlan.setupHint.step2,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_step2,"Sign in with your Volcengine account (browser SSO recommended).",,active
limits.codingPlan.setupHint.step2_remote,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_step2_remote,"Headless / remote terminals: arkcli auth login --no-browser",,active
limits.codingPlan.setupHint.step3,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_step3,"Run these, then refresh this page:",,active
limits.codingPlan.setupHint.note_app,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_note_app,"Refresh after signing in — no app restart needed.",,active
limits.codingPlan.setupHint.copy,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_copy,"Copy",,active
limits.codingPlan.setupHint.copied,ui,LimitsPage,UsageLimitsPanel,coding_plan_hint_copied,"Copied",,active
14 changes: 14 additions & 0 deletions dashboard/src/content/i18n/zh-TW/core.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@
"limits.label.qoder_ultimate": "Ultimate 免費呼叫",
"limits.label.qoder_cn_credits": "積分",
"limits.label.qoder_cn_ultimate": "Ultimate 免費呼叫",
"limits.provider.ark_coding_plan": "Ark Coding Plan",
"limits.label.ark_coding_plan_5h": "5h",
"limits.label.ark_coding_plan_weekly": "每週",
"limits.label.ark_coding_plan_monthly": "每月",
"limits.qoder_calls.detail": "已用 {{used}} / {{limit}} 次 · 剩餘 {{remaining}} 次",
"limits.hover.expires_at": "{{time}} 到期",
"limits.label.claude_5h": "5h",
Expand Down Expand Up @@ -533,6 +537,16 @@
"limits.opencodeGo.setupHint.note_app": "macOS App:使用 launchctl setenv 設定,然後重新開啟 App。",
"limits.opencodeGo.setupHint.copy": "複製",
"limits.opencodeGo.setupHint.copied": "已複製",
"limits.codingPlan.setupHint.title": "連接 Ark Coding Plan",
"limits.codingPlan.setupHint.subtitle": "額度透過本機的官方 Ark CLI(arkcli)讀取。",
"limits.codingPlan.setupHint.step1": "透過 npm 安裝 Ark CLI。",
"limits.codingPlan.setupHint.cta": "查看安裝指南",
"limits.codingPlan.setupHint.step2": "使用火山引擎帳號登入(推薦瀏覽器 SSO)。",
"limits.codingPlan.setupHint.step2_remote": "無瀏覽器 / 遠端終端:arkcli auth login --no-browser",
"limits.codingPlan.setupHint.step3": "依序執行以下指令,然後重新整理本頁:",
"limits.codingPlan.setupHint.note_app": "登入後重新整理頁面即可,無需重新啟動 App。",
"limits.codingPlan.setupHint.copy": "複製",
"limits.codingPlan.setupHint.copied": "已複製",
"skills.card.manage": "管理",
"skills.dot.synced_aria": "{{agent}}:已同步。點選可取消同步。",
"skills.dot.off_aria": "{{agent}}:未同步。點選可同步。",
Expand Down
14 changes: 14 additions & 0 deletions dashboard/src/content/i18n/zh/core.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@
"limits.label.qoder_ultimate": "Ultimate 免费调用",
"limits.label.qoder_cn_credits": "积分",
"limits.label.qoder_cn_ultimate": "Ultimate 免费调用",
"limits.provider.ark_coding_plan": "Ark Coding Plan",
"limits.label.ark_coding_plan_5h": "5h",
"limits.label.ark_coding_plan_weekly": "每周",
"limits.label.ark_coding_plan_monthly": "每月",
"limits.qoder_calls.detail": "已用 {{used}} / {{limit}} 次 · 剩余 {{remaining}} 次",
"limits.hover.expires_at": "{{time}} 到期",
"limits.label.claude_5h": "5h",
Expand Down Expand Up @@ -601,6 +605,16 @@
"limits.opencodeGo.setupHint.note_app": "macOS App:使用 launchctl setenv 设置,然后重新打开 App。",
"limits.opencodeGo.setupHint.copy": "复制",
"limits.opencodeGo.setupHint.copied": "已复制",
"limits.codingPlan.setupHint.title": "连接 Ark Coding Plan",
"limits.codingPlan.setupHint.subtitle": "额度通过本机的官方 Ark CLI(arkcli)读取。",
"limits.codingPlan.setupHint.step1": "通过 npm 安装 Ark CLI。",
"limits.codingPlan.setupHint.cta": "查看安装指南",
"limits.codingPlan.setupHint.step2": "使用火山引擎账号登录(推荐浏览器 SSO)。",
"limits.codingPlan.setupHint.step2_remote": "无浏览器 / 远程终端:arkcli auth login --no-browser",
"limits.codingPlan.setupHint.step3": "依次执行以下命令,然后刷新本页:",
"limits.codingPlan.setupHint.note_app": "登录后刷新页面即可,无需重启 App。",
"limits.codingPlan.setupHint.copy": "复制",
"limits.codingPlan.setupHint.copied": "已复制",
"skills.card.manage": "管理",
"skills.dot.synced_aria": "{{agent}}:已同步。点击可取消同步。",
"skills.dot.off_aria": "{{agent}}:未同步。点击可同步。",
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/hooks/use-limits-display-prefs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ describe("useLimitsDisplayPrefs", () => {
"antigravity",
"claude",
"codex",
"codingPlan",
"copilot",
"cursor",
"gemini",
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/hooks/use-usage-limits.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const existingLimits = {
zcode: { configured: false },
opencodeGo: { configured: false },
qoder: { configured: false },
codingPlan: { configured: false },
};

const freshLimits = {
Expand Down
12 changes: 12 additions & 0 deletions dashboard/src/hooks/use-usage-limits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ interface UsageLimitsData {
cached_at?: string | null;
source?: string | null;
};
codingPlan: {
configured: boolean;
error?: string | null;
plan_label?: string | null;
primary_window?: { used_percent: number; reset_at?: string | null } | null;
secondary_window?: { used_percent: number; reset_at?: string | null } | null;
tertiary_window?: { used_percent: number; reset_at?: string | null } | null;
cached?: boolean;
stale?: boolean;
cached_at?: string | null;
source?: string | null;
};
}

interface UsageLimitsInitialState {
Expand Down
5 changes: 5 additions & 0 deletions dashboard/src/lib/limits-providers.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const LIMIT_PROVIDER_IDS = [
"opencodeGo",
"qoder",
"qoderCn",
"codingPlan",
];

/** Keys for ProviderIcon — mono logos use inline SVG; colored logos use /brand-logos/. */
Expand All @@ -36,6 +37,8 @@ export const LIMIT_PROVIDER_ICON_KEYS = {
// The CN edition ships its own green-crescent brand mark, distinct from the
// international black double-crescent — resolved to the QODER-CN icon asset.
qoderCn: "QODER-CN",
// Volcano Engine Ark Coding Plan — own brand mark under /brand-logos/.
codingPlan: "VOLCANO-ARK",
};

export function limitProviderIconKey(id) {
Expand Down Expand Up @@ -70,6 +73,8 @@ export function limitProviderName(id) {
return copy("limits.provider.qoder");
case "qoderCn":
return copy("limits.provider.qoder_cn");
case "codingPlan":
return copy("limits.provider.ark_coding_plan");
default:
return String(id || "");
}
Expand Down
2 changes: 2 additions & 0 deletions dashboard/src/lib/pet-quips.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ const PET_LIMIT_PROVIDER_NAMES = {
zcode: "ZCode",
opencodeGo: "OpenCode Go",
qoder: "Qoder",
codingPlan: "Ark Coding Plan",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Localize the new pet-summary labels.

The new strings bypass the dashboard copy system. This causes untranslated provider and period names in pet summaries.

  • dashboard/src/lib/pet-quips.js#L310-L310: Resolve the Coding Plan provider name from localized copy.
  • dashboard/src/lib/pet-quips.js#L397-L397: Resolve the three Coding Plan period labels from localized copy.

As per coding guidelines: “Never hardcode user-facing text; add it to dashboard/src/content/copy.csv.” As per path instructions: “User-facing strings must come from dashboard/src/content/copy.csv.”

📍 Affects 1 file
  • dashboard/src/lib/pet-quips.js#L310-L310 (this comment)
  • dashboard/src/lib/pet-quips.js#L397-L397
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dashboard/src/lib/pet-quips.js` at line 310, Localize the new Coding Plan
labels in dashboard/src/lib/pet-quips.js at lines 310 and 397: resolve the
provider name and all three period labels through the dashboard copy system,
adding the required entries to dashboard/src/content/copy.csv instead of
hardcoding user-facing text.

Sources: Coding guidelines, Path instructions

};

// Unix timestamps are normally seconds; values above this order of magnitude
Expand Down Expand Up @@ -393,6 +394,7 @@ function collectPetLimitRows(limits) {
addGeneric("zcode", limits.zcode, [["GLM-5.2", limits.zcode?.primary_window], ["GLM-5 Turbo", limits.zcode?.secondary_window], ["Other", limits.zcode?.tertiary_window]]);
addGeneric("opencodeGo", limits.opencodeGo, [["5h", limits.opencodeGo?.primary_window], ["Weekly", limits.opencodeGo?.secondary_window], ["Month", limits.opencodeGo?.tertiary_window]]);
addGeneric("qoder", limits.qoder, [["Credits", limits.qoder?.primary_window], ["Ultimate Free Calls", limits.qoder?.secondary_window]]);
addGeneric("codingPlan", limits.codingPlan, [["5h", limits.codingPlan?.primary_window], ["Week", limits.codingPlan?.secondary_window], ["Month", limits.codingPlan?.tertiary_window]]);

rows.sort((a, b) => {
if (b.usedPercent !== a.usedPercent) return b.usedPercent - a.usedPercent;
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/pages/LimitsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export function LimitsPage() {
opencodeGo={usageLimits?.opencodeGo}
qoder={usageLimits?.qoder}
qoderCn={usageLimits?.qoderCn}
codingPlan={usageLimits?.codingPlan}
order={prefs.order}
visibility={prefs.visibility}
displayMode={prefs.displayMode}
Expand Down
2 changes: 2 additions & 0 deletions dashboard/src/ui/dashboard/components/ProviderIcon.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ const PROVIDER_LOGO_MAP = {
// crescent) differs from the international black double-crescent, so it gets
// its own traced asset instead of reusing qoder.svg.
"QODER-CN": "/brand-logos/qoder-cn.svg",
// Volcano Ark (火山方舟) Coding Plan — the Volcengine 3-mountain mark.
"VOLCANO-ARK": "/brand-logos/volcano-ark.svg",
};

// AnythingLLM publishes this compact mark in white. Keep the official asset
Expand Down
74 changes: 71 additions & 3 deletions dashboard/src/ui/dashboard/components/UsageLimitsPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ function renderProviderGroup(id, data, mode, expanded, onToggle) {
<ToolGroup key={id} name={limitProviderName(id)} providerId={id}>
<StatusLine>{copy("limits.status.not_connected")}</StatusLine>
{id === "opencodeGo" ? <OpenCodeGoSetupHint /> : null}
{id === "codingPlan" ? <ArkCodingPlanSetupHint /> : null}
</ToolGroup>
);
}
Expand All @@ -499,6 +500,7 @@ function renderProviderGroup(id, data, mode, expanded, onToggle) {
? renderProviderExtra(PROVIDER_LIMIT_SPECS.kiro.extra, data)
: null}
{id === "opencodeGo" ? <OpenCodeGoSetupHint /> : null}
{id === "codingPlan" ? <ArkCodingPlanSetupHint /> : null}
</ToolGroup>
);
}
Expand All @@ -514,7 +516,7 @@ function renderProviderGroup(id, data, mode, expanded, onToggle) {
badge = <StatusBadge label={copy("limits.label.antigravity_live")} tone="live" tooltip={copy("limits.tooltip.antigravity_live")} />;
}
}
if ((id === "qoder" || id === "qoderCn") && data.cached) {
if ((id === "qoder" || id === "qoderCn" || id === "codingPlan") && data.cached) {
badge = (
<StatusBadge
label={copy("limits.label.antigravity_cached")}
Expand Down Expand Up @@ -678,6 +680,72 @@ function OpenCodeGoSetupHint() {
);
}

// Ark Coding Plan (火山方舟) quota comes from the official Ark CLI (arkcli)
// running on this machine — there is no public quota endpoint, so the CLI is
// feature-detected at fetch time. When it is missing (or not signed in) the
// provider reports `configured: false` and this inline guide shows how to
// enable it, mirroring the OpenCode Go flow.
function ArkCodingPlanSetupHint() {
const [copied, setCopied] = useState(false);
const snippet = [
"npm install -g @volcengine/ark-cli",
"arkcli auth login volc-sso # browser SSO (recommended)",
"arkcli auth status # verify the session",
].join("\n");

const onCopy = async (e) => {
e.stopPropagation();
try {
await navigator.clipboard.writeText(snippet);
setCopied(true);
setTimeout(() => setCopied(false), 1600);
} catch (_e) {
// Clipboard can be unavailable in embedded or restricted contexts.
}
};

return (
<div className="mt-1.5 rounded-lg border border-oai-gray-200 dark:border-oai-gray-700/60 bg-oai-gray-50/50 dark:bg-oai-gray-900/20 p-3 text-[11px] text-oai-gray-600 dark:text-oai-gray-300">
<div className="text-[12px] font-semibold text-oai-gray-800 dark:text-oai-gray-100">{copy("limits.codingPlan.setupHint.title")}</div>
<div className="mt-0.5 leading-snug text-oai-gray-500 dark:text-oai-gray-400">{copy("limits.codingPlan.setupHint.subtitle")}</div>

<ol className="mt-2.5 space-y-2.5">
<HintStep n="1">
<div>{copy("limits.codingPlan.setupHint.step1")}</div>
<a
href="https://www.volcengine.com/docs/82379/2536875"
target="_blank"
rel="noreferrer"
onClick={(e) => e.stopPropagation()}
className="mt-1 inline-flex items-center gap-1 rounded-md bg-oai-brand/10 px-2 py-1 font-medium text-oai-brand hover:bg-oai-brand/15 transition-colors"
>
{copy("limits.codingPlan.setupHint.cta")}
<ExternalArrow />
</a>
</HintStep>
<HintStep n="2">
<div>{copy("limits.codingPlan.setupHint.step2")}</div>
<div className="mt-0.5 text-oai-gray-500 dark:text-oai-gray-400">{copy("limits.codingPlan.setupHint.step2_remote")}</div>
</HintStep>
<HintStep n="3">
<div className="flex items-center gap-2">
<span>{copy("limits.codingPlan.setupHint.step3")}</span>
<button
type="button"
onClick={onCopy}
className="shrink-0 rounded-md border border-oai-gray-300 dark:border-oai-gray-700 px-2 py-0.5 text-[10.5px] text-oai-gray-700 dark:text-oai-gray-200 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 transition-colors"
>
{copied ? copy("limits.codingPlan.setupHint.copied") : copy("limits.codingPlan.setupHint.copy")}
</button>
</div>
<pre className="mt-1.5 overflow-x-auto rounded-md bg-oai-gray-100 dark:bg-oai-gray-900/60 px-2 py-1.5 font-mono text-[10.5px] leading-relaxed whitespace-pre">{snippet}</pre>
<div className="mt-1 text-[10px] text-oai-gray-400 dark:text-oai-gray-500">{copy("limits.codingPlan.setupHint.note_app")}</div>
</HintStep>
</ol>
</div>
);
}

/**
* Width of the widest rendered row label, so every label column matches it.
* Mirrors the macOS popover behavior: bars stay aligned without reserving
Expand Down Expand Up @@ -712,8 +780,8 @@ function useWidestLabelWidth(containerRef) {
return labelWidth;
}

export function UsageLimitsPanel({ claude, codex, cursor, gemini, kimi, kiro, grok, antigravity, copilot, zcode, opencodeGo, qoder, qoderCn, order, visibility, displayMode }) {
const dataById = { claude, codex, cursor, gemini, kimi, kiro, grok, antigravity, copilot, zcode, opencodeGo, qoder, qoderCn };
export function UsageLimitsPanel({ claude, codex, cursor, gemini, kimi, kiro, grok, antigravity, copilot, zcode, opencodeGo, qoder, qoderCn, codingPlan, order, visibility, displayMode }) {
const dataById = { claude, codex, cursor, gemini, kimi, kiro, grok, antigravity, copilot, zcode, opencodeGo, qoder, qoderCn, codingPlan };
const containerRef = useRef(null);
const labelWidth = useWidestLabelWidth(containerRef);
const [expandedId, setExpandedId] = useState(null);
Expand Down
31 changes: 31 additions & 0 deletions dashboard/src/ui/dashboard/components/UsageLimitsPanel.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,37 @@ describe("UsageLimitsPanel", () => {
expect(screen.queryByText("12%")).not.toBeInTheDocument();
});

it("renders Ark Coding Plan 5h / Weekly / Monthly windows", () => {
const { rerender } = render(
<UsageLimitsPanel
codingPlan={{
configured: true,
error: null,
plan_label: "Lite",
primary_window: { used_percent: 33, reset_at: "2026-08-11T09:42:00.000Z" },
secondary_window: { used_percent: 16, reset_at: "2026-08-16T16:00:00.000Z" },
tertiary_window: { used_percent: 9, reset_at: "2026-09-09T15:59:59.000Z" },
}}
order={["codingPlan"]}
/>,
);

// Brand + tier, without repeating "Coding Plan" (title: "Ark Coding Plan Lite").
expect(screen.getByText("Ark Coding Plan Lite")).toBeInTheDocument();
expect(screen.getByText("5h")).toBeInTheDocument();
expect(screen.getByText("Weekly")).toBeInTheDocument();
expect(screen.getByText("Monthly")).toBeInTheDocument();
expect(screen.getByText("33%")).toBeInTheDocument();
expect(screen.getByText("16%")).toBeInTheDocument();
expect(screen.getByText("9%")).toBeInTheDocument();

// Not-configured fallback shows the Ark CLI setup guide.
rerender(<UsageLimitsPanel codingPlan={{ configured: false }} order={["codingPlan"]} />);
expect(screen.getByText("Ark Coding Plan")).toBeInTheDocument();
expect(screen.getByText("Not connected")).toBeInTheDocument();
expect(screen.getByText(copy("limits.codingPlan.setupHint.title"))).toBeInTheDocument();
});

it("renders Qoder credits with exact amounts in the hover detail", () => {
render(
<UsageLimitsPanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ export const PROVIDER_LIMIT_SPECS = {
];
},
},
codingPlan: {
// Volcano Ark Coding Plan quota refreshes on three windows: a rolling
// 5-hour (session), a weekly, and a monthly one. Percentages come straight
// from arkcli's usage plan payload; no client-side pacing data.
windows(data) {
return [
{ key: "5h", labelKey: "limits.label.ark_coding_plan_5h", window: data.primary_window },
{ key: "weekly", labelKey: "limits.label.ark_coding_plan_weekly", window: data.secondary_window },
{ key: "monthly", labelKey: "limits.label.ark_coding_plan_monthly", window: data.tertiary_window },
];
},
},
};

/** Static copy() anchors for validate:copy — labels resolve at runtime via spec.labelKey. */
Expand Down Expand Up @@ -222,5 +234,8 @@ export function usageLimitsLabelCopyAnchor() {
copy("limits.label.qoder_ultimate"),
copy("limits.label.qoder_cn_credits"),
copy("limits.label.qoder_cn_ultimate"),
copy("limits.label.ark_coding_plan_5h"),
copy("limits.label.ark_coding_plan_weekly"),
copy("limits.label.ark_coding_plan_monthly"),
];
}
Loading
Loading