summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/mesh/TaskOutput.tsx
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-03-02 15:18:31 +0000
committerGitHub <noreply@github.com>2026-03-02 15:18:31 +0000
commit78cb861412850889424ae7d5ae5cd952a2b90295 (patch)
tree7a6eb0693457886dbe0eea84c0c1489724791f79 /makima/frontend/src/components/mesh/TaskOutput.tsx
parent2bc1cd4717b587cd2b8ffccd723b62f888e61aa8 (diff)
downloadsoryu-78cb861412850889424ae7d5ae5cd952a2b90295.tar.gz
soryu-78cb861412850889424ae7d5ae5cd952a2b90295.zip
feat: move daemon reauth to daemons page, add contract-backed directive steps, rename Mesh to Exec (#84)
* feat: soryu-co/soryu - makima: Rename Mesh to Exec in navigation * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Add contract-backed steps to directive flow * WIP: heartbeat checkpoint
Diffstat (limited to 'makima/frontend/src/components/mesh/TaskOutput.tsx')
-rw-r--r--makima/frontend/src/components/mesh/TaskOutput.tsx110
1 files changed, 17 insertions, 93 deletions
diff --git a/makima/frontend/src/components/mesh/TaskOutput.tsx b/makima/frontend/src/components/mesh/TaskOutput.tsx
index 2db4250..1a376ad 100644
--- a/makima/frontend/src/components/mesh/TaskOutput.tsx
+++ b/makima/frontend/src/components/mesh/TaskOutput.tsx
@@ -309,7 +309,21 @@ function OutputEntryRenderer({ entry, pendingQuestionIds, onAnswerQuestion }: Ou
);
case "auth_required":
- return <AuthRequiredEntry entry={entry} />;
+ return (
+ <div className="bg-amber-900/30 border border-amber-500/50 rounded p-3 my-2">
+ <div className="flex items-center gap-2 text-amber-400 font-semibold mb-1">
+ <span>&#x26A0;</span>
+ <span>Authentication Expired{entry.toolInput?.hostname ? ` (${entry.toolInput.hostname})` : ""}</span>
+ </div>
+ <p className="text-amber-200/80 text-sm">
+ The daemon's OAuth token has expired. Go to the{" "}
+ <a href="/daemons" className="text-[#75aafc] hover:text-[#9bc3ff] underline">
+ Daemons page
+ </a>{" "}
+ to reauthorize, then retry this task.
+ </p>
+ </div>
+ );
case "supervisor_question":
return (
@@ -501,98 +515,8 @@ function SupervisorQuestionEntry({
);
}
-function AuthRequiredEntry({ entry }: { entry: TaskOutputEvent }) {
- const [authCode, setAuthCode] = useState("");
- const [submitting, setSubmitting] = useState(false);
- const [submitted, setSubmitted] = useState(false);
- const [error, setError] = useState<string | null>(null);
-
- const loginUrl = entry.toolInput?.loginUrl as string | undefined;
- const hostname = entry.toolInput?.hostname as string | undefined;
- // Get taskId from entry or fallback to toolInput (for robustness)
- const taskId = entry.taskId || (entry.toolInput?.taskId as string | undefined);
-
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- if (!authCode.trim() || !taskId) return;
-
- setSubmitting(true);
- setError(null);
-
- try {
- // Send the auth code to the task via the message endpoint
- await sendTaskMessage(taskId, `AUTH_CODE:${authCode.trim()}`);
- setSubmitted(true);
- } catch (err) {
- setError(err instanceof Error ? err.message : "Failed to submit code");
- } finally {
- setSubmitting(false);
- }
- };
-
- if (submitted) {
- return (
- <div className="bg-green-900/30 border border-green-500/50 rounded p-3 my-2">
- <div className="flex items-center gap-2 text-green-400 font-semibold">
- <span>✓</span>
- <span>Authentication code submitted</span>
- </div>
- <p className="text-green-200/80 text-sm mt-1">
- Waiting for authentication to complete...
- </p>
- </div>
- );
- }
-
- return (
- <div className="bg-amber-900/30 border border-amber-500/50 rounded p-3 my-2">
- <div className="flex items-center gap-2 text-amber-400 font-semibold mb-2">
- <span>🔐</span>
- <span>Authentication Required{hostname ? ` (${hostname})` : ""}</span>
- </div>
- <p className="text-amber-200/80 text-sm mb-3">
- The daemon's OAuth token has expired. Click the button to login, then paste the code below:
- </p>
-
- <div className="flex flex-col gap-3">
- {loginUrl ? (
- <a
- href={loginUrl}
- target="_blank"
- rel="noopener noreferrer"
- className="inline-block bg-amber-500 hover:bg-amber-400 text-black font-medium px-4 py-2 rounded transition-colors text-center"
- >
- 1. Login to Claude
- </a>
- ) : (
- <p className="text-red-400 text-sm">Login URL not available</p>
- )}
-
- <form onSubmit={handleSubmit} className="flex gap-2">
- <input
- type="text"
- value={authCode}
- onChange={(e) => setAuthCode(e.target.value)}
- placeholder="2. Paste authentication code here"
- className="flex-1 bg-[#0a1525] border border-amber-500/30 rounded px-3 py-2 text-amber-100 placeholder-amber-500/50 focus:outline-none focus:border-amber-400"
- disabled={submitting}
- />
- <button
- type="submit"
- disabled={submitting || !authCode.trim()}
- className="bg-amber-500 hover:bg-amber-400 disabled:bg-amber-700 disabled:cursor-not-allowed text-black font-medium px-4 py-2 rounded transition-colors"
- >
- {submitting ? "..." : "Submit"}
- </button>
- </form>
-
- {error && (
- <p className="text-red-400 text-sm">{error}</p>
- )}
- </div>
- </div>
- );
-}
+// AuthRequiredEntry has been removed - auth flow is now on the Daemons page.
+// The "auth_required" case in OutputEntryRenderer shows a redirect message instead.
/** Entry for phase transition confirmations */
function PhaseConfirmationEntry({