mirror of
https://github.com/logseq/logseq.git
synced 2026-05-24 12:44:22 +00:00
add #Agent and #Project
This commit is contained in:
@@ -37,3 +37,4 @@
|
||||
- DB-sync protocol reference: `docs/agent-guide/db-sync/protocol.md`.
|
||||
- New properties should be added to `logseq.db.frontend.property/built-in-properties`.
|
||||
- Avoid creating new class or property unless you have to.
|
||||
- Create db migration when adding new properties/classes.
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# M7: Agent Assignment + Session Start UI
|
||||
|
||||
## Target
|
||||
Allow users to assign an agent to a task and start a session from Logseq UI.
|
||||
Allow users to start a session from Logseq UI.
|
||||
|
||||
## Scope
|
||||
- UI control on `#Task` to select agent + project.
|
||||
- Able to run task (when both Agent and Project title && Git repo specified)
|
||||
- Create simplified sessions/create payload from task data.
|
||||
- Display session status on the task card.
|
||||
- Map session status to task status real-time
|
||||
|
||||
## Acceptance
|
||||
1) User can pick an agent for a task and start a session.
|
||||
2) Task shows status (created/running/paused/etc.).
|
||||
2) Task shows status
|
||||
3) Session created uses simplified payload shape.
|
||||
4) UI should be intuitive and fit the current ui
|
||||
|
||||
@@ -13,6 +13,11 @@ create_payload() {
|
||||
"node-title": "Check weather in Hangzhou",
|
||||
"content": "Tell me the weather today in Hangzhou.",
|
||||
"attachments": [],
|
||||
"project": {
|
||||
"id": "project-weather",
|
||||
"title": "Weather Demo",
|
||||
"repo-url": "https://github.com/logseq/logseq"
|
||||
},
|
||||
"agent": {
|
||||
"provider": "codex",
|
||||
"mode": "build",
|
||||
|
||||
@@ -224,7 +224,17 @@
|
||||
[:node-title :string]
|
||||
[:content :string]
|
||||
[:attachments [:sequential :string]]
|
||||
[:agent [:or :string :map]]])
|
||||
[:project [:map
|
||||
[:id :string]
|
||||
[:title :string]
|
||||
[:repo-url :string]]]
|
||||
[:agent [:or :string
|
||||
[:map
|
||||
[:provider {:optional true} :string]
|
||||
[:mode {:optional true} :string]
|
||||
[:permission-mode {:optional true} :string]
|
||||
[:api-token {:optional true} :string]
|
||||
[:auth-json {:optional true} :string]]]]])
|
||||
|
||||
(def sessions-message-request-schema
|
||||
[:map
|
||||
|
||||
@@ -207,7 +207,11 @@
|
||||
|
||||
:else
|
||||
(let [session (session/initial-session task audit now)
|
||||
[session events _event] (session/append-event session [] {:type "session.created" :data {:requested-by user-id} :ts 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)]
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
:source {:node-id (:node-id body)
|
||||
:node-title (:node-title body)}
|
||||
:intent {:content (:content body)}
|
||||
:project (:project body)
|
||||
:agent (:agent body)}
|
||||
(some? attachments) (assoc-in [:intent :attachments] attachments)))))
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
:node-title "Title"
|
||||
:content "Hello"
|
||||
:attachments ["https://example.com/a.png"]
|
||||
:project {:id "project-1"
|
||||
:title "Demo Project"
|
||||
:repo-url "https://github.com/example/repo"}
|
||||
:agent "codex"}
|
||||
coerced (http/coerce-http-request :sessions/create body)]
|
||||
(is (= body coerced))))
|
||||
@@ -23,7 +26,12 @@
|
||||
:node-title "Title"
|
||||
:content "Hello"
|
||||
:attachments ["https://example.com/a.png" "https://example.com/b.png"]
|
||||
:agent {:provider "codex"}}
|
||||
:project {:id "project-1"
|
||||
:title "Demo Project"
|
||||
:repo-url "https://github.com/example/repo"}
|
||||
:agent {:provider "codex"
|
||||
:api-token "token-123"
|
||||
:auth-json "{\"tokens\":{\"access_token\":\"abc\"}}"}}
|
||||
normalized (request/normalize-session-create body)]
|
||||
(is (= {:id "sess-1"
|
||||
:source {:node-id "node-1"
|
||||
@@ -31,5 +39,10 @@
|
||||
:intent {:content "Hello"
|
||||
:attachments ["https://example.com/a.png"
|
||||
"https://example.com/b.png"]}
|
||||
:agent {:provider "codex"}}
|
||||
:project {:id "project-1"
|
||||
:title "Demo Project"
|
||||
:repo-url "https://github.com/example/repo"}
|
||||
:agent {:provider "codex"
|
||||
:api-token "token-123"
|
||||
:auth-json "{\"tokens\":{\"access_token\":\"abc\"}}"}}
|
||||
normalized)))))
|
||||
|
||||
12
deps/db/src/logseq/db/frontend/class.cljs
vendored
12
deps/db/src/logseq/db/frontend/class.cljs
vendored
@@ -39,7 +39,17 @@
|
||||
|
||||
:logseq.class/Task
|
||||
{:title "Task"
|
||||
:schema {:properties [:logseq.property/status :logseq.property/priority :logseq.property/deadline :logseq.property/scheduled]}}
|
||||
:schema {:properties [:logseq.property/status :logseq.property/priority :logseq.property/deadline
|
||||
:logseq.property/scheduled :logseq.property/project :logseq.property/agent]}}
|
||||
|
||||
:logseq.class/Project
|
||||
{:title "Project"
|
||||
:schema {:properties [:logseq.property/git-repo]
|
||||
:required-properties [:logseq.property/git-repo]}}
|
||||
|
||||
:logseq.class/Agent
|
||||
{:title "Agent"
|
||||
:schema {:properties [:logseq.property/agent-api-token :logseq.property/agent-auth-json]}}
|
||||
|
||||
:logseq.class/Query
|
||||
{:title "Query"
|
||||
|
||||
32
deps/db/src/logseq/db/frontend/property.cljs
vendored
32
deps/db/src/logseq/db/frontend/property.cljs
vendored
@@ -406,7 +406,37 @@
|
||||
:schema {:type :property
|
||||
:hide? true}}
|
||||
|
||||
;; TODO: Add more props :Assignee, :Estimate, :Cycle, :Project
|
||||
;; TODO: Add more props :Assignee, :Estimate, :Cycle
|
||||
|
||||
:logseq.property/project
|
||||
{:title "Project"
|
||||
:schema {:type :page
|
||||
:public? true
|
||||
:classes #{:logseq.class/Project}}
|
||||
:queryable? true}
|
||||
:logseq.property/agent
|
||||
{:title "Agent"
|
||||
:schema {:type :page
|
||||
:public? true
|
||||
:classes #{:logseq.class/Agent}}
|
||||
:queryable? true}
|
||||
:logseq.property/git-repo
|
||||
{:title "Git Repo"
|
||||
:schema {:type :url
|
||||
:public? true
|
||||
:view-context :page}
|
||||
:queryable? true}
|
||||
:logseq.property/agent-api-token
|
||||
{:title "API Token"
|
||||
:schema {:type :string
|
||||
:public? true
|
||||
:view-context :page}}
|
||||
:logseq.property/agent-auth-json
|
||||
{:title "auth.json"
|
||||
:schema {:type :string
|
||||
:public? true
|
||||
:view-context :page}
|
||||
:properties {:logseq.property/description "Store a text block with the auth.json content."}}
|
||||
|
||||
:logseq.property/icon {:title "Icon"
|
||||
:schema {:type :map}}
|
||||
|
||||
2
deps/db/src/logseq/db/frontend/schema.cljs
vendored
2
deps/db/src/logseq/db/frontend/schema.cljs
vendored
@@ -30,7 +30,7 @@
|
||||
(map (juxt :major :minor)
|
||||
[(parse-schema-version x) (parse-schema-version y)])))
|
||||
|
||||
(def version (parse-schema-version "65.22"))
|
||||
(def version (parse-schema-version "65.23"))
|
||||
|
||||
(defn major-version
|
||||
"Return a number.
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
hidden-pages (concat (build-initial-views) (build-favorites-page))
|
||||
;; These classes bootstrap our tags and properties as they depend on each other e.g.
|
||||
;; Root <-> Tag, classes-tx depends on logseq.property.class/extends, properties-tx depends on Property
|
||||
bootstrap-class? (fn [c] (contains? #{:logseq.class/Root :logseq.class/Property :logseq.class/Tag :logseq.class/Template} (:db/ident c)))
|
||||
bootstrap-class? (fn [c] (contains? #{:logseq.class/Root :logseq.class/Property :logseq.class/Tag :logseq.class/Template :logseq.class/Agent :logseq.class/Project} (:db/ident c)))
|
||||
bootstrap-classes (filter bootstrap-class? default-classes)
|
||||
bootstrap-class-ids (map #(select-keys % [:db/ident :block/uuid]) bootstrap-classes)
|
||||
classes-tx (concat (map #(dissoc % :db/ident) bootstrap-classes)
|
||||
|
||||
@@ -20,6 +20,6 @@
|
||||
:compression compression}]
|
||||
(p/let [zip-blob (.generateAsync zip opts
|
||||
(when progress-fn
|
||||
(fn [metadata]
|
||||
(fn [^js metadata]
|
||||
(progress-fn (.-percent metadata)))))]
|
||||
(make-file zip-blob (str zip-filename ".zip") {:type "application/zip"}))))
|
||||
|
||||
@@ -26,7 +26,15 @@
|
||||
:else nil)))
|
||||
reaction-username (fn [reaction]
|
||||
(let [user (:logseq.property/created-by-ref reaction)]
|
||||
(:block/title (db/entity (:db/id user)))))
|
||||
(cond
|
||||
(map? user)
|
||||
(if (:db/id user)
|
||||
(:logseq.property.user/name user)
|
||||
(or (:logseq.property.user/name user)
|
||||
(:block/title user)))
|
||||
(number? user)
|
||||
(:logseq.property.user/name (db/entity user))
|
||||
:else nil)))
|
||||
summary (reduce (fn [acc reaction]
|
||||
(let [emoji-id (:logseq.property.reaction/emoji-id reaction)
|
||||
user-id (reaction-user-id reaction)
|
||||
@@ -43,10 +51,10 @@
|
||||
reactions)]
|
||||
(->> summary
|
||||
(map (fn [[emoji-id {:keys [count reacted-by-me? usernames]}]]
|
||||
{:emoji-id emoji-id
|
||||
:count count
|
||||
:reacted-by-me? (boolean reacted-by-me?)
|
||||
:usernames (when (seq usernames)
|
||||
(->> usernames sort vec))}))
|
||||
(cond-> {:emoji-id emoji-id
|
||||
:count count
|
||||
:reacted-by-me? (boolean reacted-by-me?)}
|
||||
(seq usernames)
|
||||
(assoc :usernames (->> usernames sort vec)))))
|
||||
(sort-by (juxt (comp - :count) :emoji-id))
|
||||
vec)))
|
||||
|
||||
@@ -945,11 +945,11 @@
|
||||
fade-in? true
|
||||
root-margin 100}}]
|
||||
(let [[visible? set-visible!] (rum/use-state initial-state)
|
||||
inViewState (useInView #js {:initialInView initial-state
|
||||
:rootMargin (str root-margin "px")
|
||||
:triggerOnce trigger-once?
|
||||
:onChange (fn [in-view? _entry]
|
||||
(set-visible! in-view?))})
|
||||
^js inViewState (useInView #js {:initialInView initial-state
|
||||
:rootMargin (str root-margin "px")
|
||||
:triggerOnce trigger-once?
|
||||
:onChange (fn [in-view? _entry]
|
||||
(set-visible! in-view?))})
|
||||
ref (.-ref inViewState)]
|
||||
(lazy-visible-inner visible? content-fn ref fade-in? placeholder))))
|
||||
|
||||
|
||||
@@ -189,7 +189,14 @@
|
||||
["65.20" {:properties [:logseq.property.class/bidirectional-property-title :logseq.property.class/enable-bidirectional?]}]
|
||||
["65.21" {:properties [:logseq.property.sync/large-title-object]}]
|
||||
["65.22" {:properties [:logseq.property.reaction/emoji-id
|
||||
:logseq.property.reaction/target]}]])
|
||||
:logseq.property.reaction/target]}]
|
||||
["65.23" {:classes [:logseq.class/Project
|
||||
:logseq.class/Agent]
|
||||
:properties [:logseq.property/project
|
||||
:logseq.property/agent
|
||||
:logseq.property/git-repo
|
||||
:logseq.property/agent-api-token
|
||||
:logseq.property/agent-auth-json]}]])
|
||||
|
||||
(let [[major minor] (last (sort (map (comp (juxt :major :minor) db-schema/parse-schema-version first)
|
||||
schema-version->updates)))]
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
[cljs.test :refer [deftest is]]
|
||||
[datascript.core :as d]
|
||||
[frontend.worker.db.migrate :as db-migrate]
|
||||
[logseq.db :as ldb]))
|
||||
[logseq.db :as ldb]
|
||||
[logseq.db.test.helper :as db-test]))
|
||||
|
||||
(deftest ensure-built-in-data-exists!
|
||||
(let [db-transit (str (fs-node/readFileSync "src/test/migration/64.8.transit"))
|
||||
@@ -20,3 +21,23 @@
|
||||
(is (= graph-created-at
|
||||
(:kv/value (d/entity @conn :logseq.kv/graph-created-at)))
|
||||
"Graph created at not changed by fn")))
|
||||
|
||||
(deftest migrate-adds-project-agent-builtins
|
||||
(let [conn (db-test/create-conn)
|
||||
_ (d/transact! conn [{:db/ident :logseq.kv/schema-version
|
||||
:kv/value {:major 65 :minor 22}}])
|
||||
remove-idents [:logseq.class/Project
|
||||
:logseq.class/Agent
|
||||
:logseq.property/project
|
||||
:logseq.property/git-repo
|
||||
:logseq.property/agent-api-token
|
||||
:logseq.property/agent-auth-json]
|
||||
_ (doseq [ident remove-idents
|
||||
:let [eid (d/entid @conn ident)]
|
||||
:when eid]
|
||||
(d/transact! conn [[:db/retractEntity eid]]))
|
||||
_ (db-migrate/migrate conn :target-version "65.23")]
|
||||
(is (= {:major 65 :minor 23}
|
||||
(:kv/value (d/entity @conn :logseq.kv/schema-version))))
|
||||
(doseq [ident remove-idents]
|
||||
(is (some? (d/entity @conn ident))))))
|
||||
|
||||
Reference in New Issue
Block a user