mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-04 07:20:10 +00:00
Root promotion: request_directory gains primary; granted folder can become the workspace
One-way, once, scratch-primary sessions only; consent card says workspace. Live roots + shell repoint, persisted; engine rebuilds fully anchored after the turn.
This commit is contained in:
@@ -751,7 +751,7 @@ export function App() {
|
||||
if (unattendedRef.current) break;
|
||||
setItems((p) => [
|
||||
...p,
|
||||
{ kind: "dirreq", reason: d.reason || "", path: d.path || "", writable: !!d.writable },
|
||||
{ kind: "dirreq", reason: d.reason || "", path: d.path || "", writable: !!d.writable, primary: !!d.primary },
|
||||
]);
|
||||
break;
|
||||
case "tool_requested":
|
||||
|
||||
@@ -26,9 +26,19 @@ export function DirectoryRequestCard({
|
||||
<div className="dirreq-card">
|
||||
<div className="dirreq-head">
|
||||
<Icon name="folderPlus" size={16} className="ico" />
|
||||
<span>The agent is requesting access to a folder</span>
|
||||
<span>
|
||||
{item.primary
|
||||
? "The agent asks to make a folder this session's workspace"
|
||||
: "The agent is requesting access to a folder"}
|
||||
</span>
|
||||
</div>
|
||||
{item.reason && <div className="dirreq-reason">“{item.reason}”</div>}
|
||||
{item.primary && (
|
||||
<div className="dirreq-reason">
|
||||
Granting makes this folder the session's primary working directory (read-write);
|
||||
the scratch directory stays available for temporary files and artifacts.
|
||||
</div>
|
||||
)}
|
||||
<div className="dirreq-pathrow">
|
||||
<input
|
||||
className="dirreq-path"
|
||||
@@ -41,16 +51,22 @@ export function DirectoryRequestCard({
|
||||
</button>
|
||||
</div>
|
||||
<div className="dirreq-actions">
|
||||
<label className="dirreq-access">
|
||||
<input type="checkbox" checked={writable} onChange={(e) => setWritable(e.target.checked)} />
|
||||
Allow writing (read-write)
|
||||
</label>
|
||||
{!item.primary && (
|
||||
<label className="dirreq-access">
|
||||
<input type="checkbox" checked={writable} onChange={(e) => setWritable(e.target.checked)} />
|
||||
Allow writing (read-write)
|
||||
</label>
|
||||
)}
|
||||
<span className="spacer" />
|
||||
<button className="btn" onClick={() => onRespond(false)}>
|
||||
Decline
|
||||
</button>
|
||||
<button className="btn primary" disabled={!path.trim()} onClick={() => onRespond(true, path.trim(), writable)}>
|
||||
Grant access
|
||||
<button
|
||||
className="btn primary"
|
||||
disabled={!path.trim()}
|
||||
onClick={() => onRespond(true, path.trim(), item.primary ? true : writable)}
|
||||
>
|
||||
{item.primary ? "Make workspace" : "Grant access"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -378,11 +378,19 @@ export function InboxItemCard({
|
||||
onClick={() =>
|
||||
onResolve(
|
||||
item.id,
|
||||
JSON.stringify({ granted: true, path: item.data?.path || "", writable: !!item.data?.writable }),
|
||||
JSON.stringify({
|
||||
granted: true,
|
||||
path: item.data?.path || "",
|
||||
writable: item.data?.primary ? true : !!item.data?.writable,
|
||||
}),
|
||||
)
|
||||
}
|
||||
>
|
||||
{item.data?.path ? "Grant" : "Grant (no folder)"}
|
||||
{item.data?.path
|
||||
? item.data?.primary
|
||||
? "Make workspace"
|
||||
: "Grant"
|
||||
: "Grant (no folder)"}
|
||||
</button>
|
||||
<button className={BTN_BORDERED} onClick={() => onResolve(item.id, JSON.stringify({ granted: false }))}>
|
||||
Deny
|
||||
|
||||
@@ -144,6 +144,7 @@ export type Item =
|
||||
reason: string;
|
||||
path?: string;
|
||||
writable?: boolean;
|
||||
primary?: boolean; // root promotion: the folder becomes the session's workspace
|
||||
resolved?: "granted" | "denied";
|
||||
}
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user