mirror of
https://github.com/logseq/logseq.git
synced 2026-05-27 06:04:23 +00:00
allow custom git branch
This commit is contained in:
76
deps/workers/src/logseq/agents/do.cljs
vendored
76
deps/workers/src/logseq/agents/do.cljs
vendored
@@ -259,6 +259,44 @@
|
||||
(or (some-> (aget env "GITHUB_DEFAULT_BASE_BRANCH") str string/trim not-empty)
|
||||
"main"))
|
||||
|
||||
(defn- github-default-branch-token
|
||||
[^js env]
|
||||
(or (source-control/push-token env)
|
||||
(source-control/pr-token env)))
|
||||
|
||||
(defn- task-requested-base-branch
|
||||
[task]
|
||||
(or (some-> (get-in task [:project :base-branch]) source-control/sanitize-branch-name)
|
||||
(some-> (get-in task [:project :branch]) source-control/sanitize-branch-name)))
|
||||
|
||||
(defn- <ensure-task-base-branch!
|
||||
[^js env task]
|
||||
(let [repo-url (some-> (get-in task [:project :repo-url]) str string/trim not-empty)
|
||||
requested-base (task-requested-base-branch task)]
|
||||
(cond
|
||||
(not (map? task))
|
||||
(p/resolved task)
|
||||
|
||||
(not (map? (:project task)))
|
||||
(p/resolved task)
|
||||
|
||||
(string? requested-base)
|
||||
(p/resolved (assoc-in task [:project :base-branch] requested-base))
|
||||
|
||||
(not (string? repo-url))
|
||||
(p/resolved task)
|
||||
|
||||
:else
|
||||
(p/let [detected-base (source-control/<default-branch! env
|
||||
(github-default-branch-token env)
|
||||
repo-url)
|
||||
detected-base (source-control/sanitize-branch-name detected-base)
|
||||
fallback-base (source-control/sanitize-branch-name (default-base-branch env))
|
||||
resolved-base (or detected-base fallback-base)]
|
||||
(if (string? resolved-base)
|
||||
(assoc-in task [:project :base-branch] resolved-base)
|
||||
task)))))
|
||||
|
||||
(defn- error-reason
|
||||
[error]
|
||||
(let [reason (some-> error ex-data :reason)]
|
||||
@@ -516,23 +554,24 @@
|
||||
(http/forbidden)
|
||||
|
||||
:else
|
||||
(let [session (session/initial-session task audit now)
|
||||
[session events _event] (session/append-event session [] {:type "session.created"
|
||||
:data {:requested-by user-id
|
||||
:project (:project task)
|
||||
:agent (:agent task)}
|
||||
:ts now})]
|
||||
(p/let [_ (<put-session! self session)
|
||||
_ (<put-events! self events)
|
||||
_ (<provision-runtime! self task task-id)
|
||||
updated-session (<get-session self)]
|
||||
(http/json-response :sessions/create
|
||||
{:session-id task-id
|
||||
:status (or (:status updated-session)
|
||||
(:status session))
|
||||
:runtime-provider (session-runtime-provider updated-session)
|
||||
:terminal-enabled (session-terminal-enabled? updated-session)
|
||||
:stream-url (stream-url request task-id)})))))))))))
|
||||
(p/let [task (<ensure-task-base-branch! (.-env self) task)]
|
||||
(let [session (session/initial-session task audit now)
|
||||
[session events _event] (session/append-event session [] {:type "session.created"
|
||||
:data {:requested-by user-id
|
||||
:project (:project task)
|
||||
:agent (:agent task)}
|
||||
:ts now})]
|
||||
(p/let [_ (<put-session! self session)
|
||||
_ (<put-events! self events)
|
||||
_ (<provision-runtime! self task task-id)
|
||||
updated-session (<get-session self)]
|
||||
(http/json-response :sessions/create
|
||||
{:session-id task-id
|
||||
:status (or (:status updated-session)
|
||||
(:status session))
|
||||
:runtime-provider (session-runtime-provider updated-session)
|
||||
:terminal-enabled (session-terminal-enabled? updated-session)
|
||||
:stream-url (stream-url request task-id)}))))))))))))
|
||||
|
||||
(defn- handle-status [^js self _request]
|
||||
(p/let [session (<get-session self)]
|
||||
@@ -692,8 +731,7 @@
|
||||
(p/let [pr-token (source-control/pr-token (.-env self))
|
||||
requested-base-branch (source-control/sanitize-branch-name (:base-branch body))
|
||||
default-base (source-control/sanitize-branch-name (default-base-branch (.-env self)))
|
||||
detected-base-branch (when (and (nil? requested-base-branch)
|
||||
(string? pr-token))
|
||||
detected-base-branch (when (nil? requested-base-branch)
|
||||
(source-control/<default-branch! (.-env self)
|
||||
pr-token
|
||||
repo-url))
|
||||
|
||||
@@ -146,25 +146,24 @@
|
||||
|
||||
(defn <default-branch!
|
||||
[^js env token repo-url]
|
||||
(if-not (string? token)
|
||||
(p/resolved nil)
|
||||
(if-let [{:keys [provider owner name]} (repo-ref repo-url)]
|
||||
(if-not (= "github" provider)
|
||||
(p/resolved nil)
|
||||
(let [url (str (api-base-url env) "/repos/" owner "/" name)
|
||||
headers (doto (js/Headers.)
|
||||
(.set "accept" "application/vnd.github+json")
|
||||
(.set "authorization" (str "Bearer " token))
|
||||
(.set "user-agent" (user-agent env))
|
||||
(.set "x-github-api-version" "2022-11-28"))]
|
||||
(p/let [resp (js/fetch url #js {:method "GET" :headers headers})
|
||||
status (.-status resp)
|
||||
text (.text resp)
|
||||
payload (parse-json-safe text)]
|
||||
(if (<= 200 status 299)
|
||||
(some-> (:default_branch payload) non-empty-str)
|
||||
nil))))
|
||||
(p/resolved nil))))
|
||||
(if-let [{:keys [provider owner name]} (repo-ref repo-url)]
|
||||
(if-not (= "github" provider)
|
||||
(p/resolved nil)
|
||||
(let [url (str (api-base-url env) "/repos/" owner "/" name)
|
||||
headers (doto (js/Headers.)
|
||||
(.set "accept" "application/vnd.github+json")
|
||||
(.set "user-agent" (user-agent env))
|
||||
(.set "x-github-api-version" "2022-11-28"))
|
||||
_ (when (string? token)
|
||||
(.set headers "authorization" (str "Bearer " token)))]
|
||||
(p/let [resp (js/fetch url #js {:method "GET" :headers headers})
|
||||
status (.-status resp)
|
||||
text (.text resp)
|
||||
payload (parse-json-safe text)]
|
||||
(if (<= 200 status 299)
|
||||
(some-> (:default_branch payload) non-empty-str)
|
||||
nil))))
|
||||
(p/resolved nil)))
|
||||
|
||||
(defn <create-pull-request!
|
||||
[^js env token repo-url {:keys [title body head-branch base-branch draft]}]
|
||||
|
||||
@@ -230,7 +230,8 @@
|
||||
[:project [:map
|
||||
[:id :string]
|
||||
[:title :string]
|
||||
[:repo-url :string]]]
|
||||
[:repo-url :string]
|
||||
[:base-branch {:optional true} :string]]]
|
||||
[:agent [:or :string
|
||||
[:map
|
||||
[:provider {:optional true} :string]
|
||||
|
||||
@@ -550,6 +550,8 @@
|
||||
(remove nil?))
|
||||
[active-view set-active-view!] (rum/use-state "chat")
|
||||
[draft set-draft!] (rum/use-state "")
|
||||
[start-branch set-start-branch!] (rum/use-state "")
|
||||
[starting-session? set-starting-session?!] (rum/use-state false)
|
||||
[publish-mode set-publish-mode!] (rum/use-state nil)
|
||||
[terminal-visible? set-terminal-visible!] (rum/use-state false)
|
||||
[terminal-status set-terminal-status!] (rum/use-state :idle)
|
||||
@@ -563,9 +565,13 @@
|
||||
terminal-open-disabled? (or (not session-started?)
|
||||
(not (string? terminal-url)))
|
||||
trimmed-draft (string/trim (or draft ""))
|
||||
selected-start-branch (normalized-text start-branch)
|
||||
busy? (contains? #{"submitted" "streaming"} chat-status)
|
||||
input-disabled? (or (not session-started?) (not (agent-handler/task-ready? block)))
|
||||
publish-busy? (some? publish-mode)
|
||||
start-session-disabled? (or starting-session?
|
||||
session-started?
|
||||
(not (agent-handler/task-ready? block)))
|
||||
publish-disabled? (or input-disabled? busy? publish-busy?)
|
||||
can-send? (and (not input-disabled?)
|
||||
(not (string/blank? trimmed-draft))
|
||||
@@ -576,6 +582,15 @@
|
||||
(set-draft! "")
|
||||
(-> (.sendMessage chat #js {:text trimmed-draft})
|
||||
(.catch (fn [_] nil)))))
|
||||
start-session! (fn []
|
||||
(when (and base session-id (not start-session-disabled?))
|
||||
(set-starting-session?! true)
|
||||
(let [opts (cond-> {}
|
||||
(string? selected-start-branch)
|
||||
(assoc :base-branch selected-start-branch))]
|
||||
(-> (agent-handler/<start-session! block opts)
|
||||
(p/catch (fn [_] nil))
|
||||
(p/finally (fn [] (set-starting-session?! false)))))))
|
||||
publish! (fn [create-pr?]
|
||||
(when (and base session-id (not publish-disabled?))
|
||||
(set-publish-mode! (if create-pr? :pr :push))
|
||||
@@ -786,6 +801,27 @@
|
||||
(when (and terminal-tab-active? (string? terminal-error))
|
||||
[:div {:class "mt-0.5 rounded-lg border border-red-300/40 bg-red-500/5 px-3 py-1.5 text-xs text-red-500"}
|
||||
terminal-error])
|
||||
(when-not session-started?
|
||||
[:div {:class "flex items-end gap-2 rounded-xl border border-border/70 bg-muted/30 p-2"}
|
||||
[:div.flex-1
|
||||
[:div.mb-1.text-xs.opacity-70 "Base branch (optional)"]
|
||||
(shui/input
|
||||
{:placeholder "Leave empty to auto-detect from GitHub"
|
||||
:value start-branch
|
||||
:disabled starting-session?
|
||||
:on-change #(set-start-branch! (or (.. % -target -value) ""))
|
||||
:on-key-down (fn [^js e]
|
||||
(when (= "Enter" (.-key e))
|
||||
(.preventDefault e)
|
||||
(start-session!)))})]
|
||||
(shui/button
|
||||
{:size :sm
|
||||
:class "h-9 px-3 text-xs"
|
||||
:disabled start-session-disabled?
|
||||
:on-click (fn [_] (start-session!))}
|
||||
(if starting-session?
|
||||
"Starting..."
|
||||
"Start session"))])
|
||||
[:div {:class "relative flex flex-1 flex-col overflow-hidden rounded-2xl border border-border/80 bg-gradient-to-b from-background via-background to-muted/40 shadow-sm"
|
||||
:style {:minHeight 0}}
|
||||
[:div.h-full.min-h-0
|
||||
|
||||
@@ -2532,10 +2532,7 @@
|
||||
:disabled (not ready?)
|
||||
:on-click (fn [e]
|
||||
(util/stop e)
|
||||
(agent-chat/open-agent-chat-dialog! block)
|
||||
(when-not session-started?
|
||||
(-> (agent-handler/<start-session! block)
|
||||
(p/catch (fn [_] nil)))))}
|
||||
(agent-chat/open-agent-chat-dialog! block))}
|
||||
(cond
|
||||
running? "Running"
|
||||
session-started? "Thread"
|
||||
|
||||
@@ -47,36 +47,42 @@
|
||||
(string? auth-json) (assoc :auth-json auth-json))))
|
||||
|
||||
(defn- project-config
|
||||
[project-page]
|
||||
(let [repo-url (blank->nil (pu/get-block-property-value project-page :logseq.property/git-repo))
|
||||
project-id (some-> (:block/uuid project-page) str)
|
||||
title (blank->nil (:block/title project-page))]
|
||||
(when (and project-id title repo-url)
|
||||
{:id project-id
|
||||
:title title
|
||||
:repo-url repo-url})))
|
||||
([project-page]
|
||||
(project-config project-page nil))
|
||||
([project-page {:keys [base-branch]}]
|
||||
(let [repo-url (blank->nil (pu/get-block-property-value project-page :logseq.property/git-repo))
|
||||
project-id (some-> (:block/uuid project-page) str)
|
||||
title (blank->nil (:block/title project-page))
|
||||
base-branch (blank->nil base-branch)]
|
||||
(when (and project-id title repo-url)
|
||||
(cond-> {:id project-id
|
||||
:title title
|
||||
:repo-url repo-url}
|
||||
(string? base-branch) (assoc :base-branch base-branch))))))
|
||||
|
||||
(defn- task-context
|
||||
[block]
|
||||
(let [block-uuid (:block/uuid block)
|
||||
node-id (some-> block-uuid str)
|
||||
node-title (or (blank->nil (:block/raw-title block))
|
||||
(blank->nil (:block/title block))
|
||||
"")
|
||||
content (or (blank->nil (:block/raw-title block))
|
||||
(blank->nil (:block/title block))
|
||||
"")
|
||||
project-page (:logseq.property/project block)
|
||||
agent-page (:logseq.property/agent block)
|
||||
project (when project-page (project-config project-page))
|
||||
agent (when agent-page (agent-config agent-page))]
|
||||
{:block-uuid block-uuid
|
||||
:node-id node-id
|
||||
:node-title node-title
|
||||
:content content
|
||||
:attachments []
|
||||
:project project
|
||||
:agent agent}))
|
||||
([block]
|
||||
(task-context block nil))
|
||||
([block opts]
|
||||
(let [block-uuid (:block/uuid block)
|
||||
node-id (some-> block-uuid str)
|
||||
node-title (or (blank->nil (:block/raw-title block))
|
||||
(blank->nil (:block/title block))
|
||||
"")
|
||||
content (or (blank->nil (:block/raw-title block))
|
||||
(blank->nil (:block/title block))
|
||||
"")
|
||||
project-page (:logseq.property/project block)
|
||||
agent-page (:logseq.property/agent block)
|
||||
project (when project-page (project-config project-page opts))
|
||||
agent (when agent-page (agent-config agent-page))]
|
||||
{:block-uuid block-uuid
|
||||
:node-id node-id
|
||||
:node-title node-title
|
||||
:content content
|
||||
:attachments []
|
||||
:project project
|
||||
:agent agent})))
|
||||
|
||||
(defn task-ready?
|
||||
[block]
|
||||
@@ -87,19 +93,21 @@
|
||||
(> (count (:block/title block)) 4))))
|
||||
|
||||
(defn build-session-body
|
||||
[block]
|
||||
(let [{:keys [block-uuid node-id node-title content attachments project agent]} (task-context block)
|
||||
session-id (some-> block-uuid str)]
|
||||
(when (and session-id node-id (string? node-title) (string? content) (map? project) (map? agent))
|
||||
{:session-id session-id
|
||||
:node-id node-id
|
||||
:node-title node-title
|
||||
:content content
|
||||
:attachments attachments
|
||||
:project project
|
||||
:agent agent
|
||||
:capabilities {:push-enabled true
|
||||
:pr-enabled true}})))
|
||||
([block]
|
||||
(build-session-body block nil))
|
||||
([block opts]
|
||||
(let [{:keys [block-uuid node-id node-title content attachments project agent]} (task-context block opts)
|
||||
session-id (some-> block-uuid str)]
|
||||
(when (and session-id node-id (string? node-title) (string? content) (map? project) (map? agent))
|
||||
{:session-id session-id
|
||||
:node-id node-id
|
||||
:node-title node-title
|
||||
:content content
|
||||
:attachments attachments
|
||||
:project project
|
||||
:agent agent
|
||||
:capabilities {:push-enabled true
|
||||
:pr-enabled true}}))))
|
||||
|
||||
(def ^:private stream-reconnect-delay-ms 1500)
|
||||
|
||||
@@ -414,52 +422,54 @@
|
||||
nil))))))))
|
||||
|
||||
(defn <start-session!
|
||||
[block]
|
||||
(let [base (db-sync/http-base)]
|
||||
(cond
|
||||
(not base)
|
||||
(do
|
||||
(notification/show! "DB sync is not configured." :error false)
|
||||
(p/resolved nil))
|
||||
([block]
|
||||
(<start-session! block nil))
|
||||
([block opts]
|
||||
(let [base (db-sync/http-base)]
|
||||
(cond
|
||||
(not base)
|
||||
(do
|
||||
(notification/show! "DB sync is not configured." :error false)
|
||||
(p/resolved nil))
|
||||
|
||||
(not (task-ready? block))
|
||||
(do
|
||||
(notification/show! "Task needs Project (with Git Repo) and Agent." :warning)
|
||||
(p/resolved nil))
|
||||
(not (task-ready? block))
|
||||
(do
|
||||
(notification/show! "Task needs Project (with Git Repo) and Agent." :warning)
|
||||
(p/resolved nil))
|
||||
|
||||
:else
|
||||
(p/let [_ (js/Promise. user-handler/task--ensure-id&access-token)
|
||||
raw-body (build-session-body block)
|
||||
body (coerce-http-request :sessions/create raw-body)]
|
||||
(if (nil? body)
|
||||
(do
|
||||
(notification/show! "Invalid agent session payload." :error false)
|
||||
nil)
|
||||
(p/let [resp (db-sync/fetch-json (str base "/sessions")
|
||||
{:method "POST"
|
||||
:headers {"content-type" "application/json"}
|
||||
:body (js/JSON.stringify (clj->js body))}
|
||||
{:response-schema :sessions/create})
|
||||
session-id (:session-id resp)
|
||||
status (:status resp)
|
||||
stream-url (:stream-url resp)
|
||||
block-uuid (:block/uuid block)
|
||||
_ (when-let [raw-message (message-body (:content raw-body))]
|
||||
(let [coerced (coerce-http-request :sessions/message raw-message)
|
||||
msg-body (if (map? coerced) coerced raw-message)]
|
||||
(db-sync/fetch-json (str base "/sessions/" session-id "/messages")
|
||||
:else
|
||||
(p/let [_ (js/Promise. user-handler/task--ensure-id&access-token)
|
||||
raw-body (build-session-body block opts)
|
||||
body (coerce-http-request :sessions/create raw-body)]
|
||||
(if (nil? body)
|
||||
(do
|
||||
(notification/show! "Invalid agent session payload." :error false)
|
||||
nil)
|
||||
(p/let [resp (db-sync/fetch-json (str base "/sessions")
|
||||
{:method "POST"
|
||||
:headers {"content-type" "application/json"}
|
||||
:body (js/JSON.stringify (clj->js msg-body))}
|
||||
{:response-schema :sessions/message})))]
|
||||
(update-session-state! block-uuid {:session-id session-id
|
||||
:status status
|
||||
:runtime-provider (:runtime-provider resp)
|
||||
:terminal-enabled (true? (:terminal-enabled resp))
|
||||
:stream-url stream-url
|
||||
:started-at (util/time-ms)})
|
||||
(<connect-session-stream! block-uuid stream-url)
|
||||
resp))))))
|
||||
:body (js/JSON.stringify (clj->js body))}
|
||||
{:response-schema :sessions/create})
|
||||
session-id (:session-id resp)
|
||||
status (:status resp)
|
||||
stream-url (:stream-url resp)
|
||||
block-uuid (:block/uuid block)
|
||||
_ (when-let [raw-message (message-body (:content raw-body))]
|
||||
(let [coerced (coerce-http-request :sessions/message raw-message)
|
||||
msg-body (if (map? coerced) coerced raw-message)]
|
||||
(db-sync/fetch-json (str base "/sessions/" session-id "/messages")
|
||||
{:method "POST"
|
||||
:headers {"content-type" "application/json"}
|
||||
:body (js/JSON.stringify (clj->js msg-body))}
|
||||
{:response-schema :sessions/message})))]
|
||||
(update-session-state! block-uuid {:session-id session-id
|
||||
:status status
|
||||
:runtime-provider (:runtime-provider resp)
|
||||
:terminal-enabled (true? (:terminal-enabled resp))
|
||||
:stream-url stream-url
|
||||
:started-at (util/time-ms)})
|
||||
(<connect-session-stream! block-uuid stream-url)
|
||||
resp)))))))
|
||||
|
||||
(defn- publish-request-body
|
||||
[{:keys [title body commit-message head-branch base-branch create-pr? force?]}]
|
||||
|
||||
Reference in New Issue
Block a user