@datalayer/agent-runtimes 1.5.36 → 1.5.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-embed/datalayer-app-main.js +69 -69
- package/lib/apps/apps/sessionRules.d.ts +81 -0
- package/lib/apps/apps/sessionRules.js +122 -0
- package/lib/apps/plugins/app-rules/AppRulesCard.d.ts +14 -1
- package/lib/apps/plugins/app-rules/AppRulesCard.js +56 -5
- package/lib/apps/plugins/app-rules/index.d.ts +2 -1
- package/lib/apps/plugins/app-rules/index.js +4 -3
- package/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rule a person adds to a running session (SHIELD.md §6.3, SH-54): the
|
|
3
|
+
* session API's `/apps/sessions/{uid}/rules`, read and written from the
|
|
4
|
+
* Rules card beside the page, and the words it says.
|
|
5
|
+
*
|
|
6
|
+
* The rule is the Shield's own shape (`@datalayer/agent-shield`'s `Rule`): a
|
|
7
|
+
* name, a decision — `allow`, `ask`, `deny` — and what it names: classes
|
|
8
|
+
* (read, write, send, buy, delete, execute), a harness's kinds, where, paths,
|
|
9
|
+
* commands. It may only tighten: one that would permit more than the
|
|
10
|
+
* organization's rules is refused by the runtime in a sentence, shown as is.
|
|
11
|
+
* The phone's panel speaks to the same three routes with the same shapes.
|
|
12
|
+
*
|
|
13
|
+
* @module apps/apps/sessionRules
|
|
14
|
+
*/
|
|
15
|
+
export declare const SESSION_RULE_DECISIONS: readonly ["allow", "ask", "deny"];
|
|
16
|
+
export type SessionRuleDecision = (typeof SESSION_RULE_DECISIONS)[number];
|
|
17
|
+
export declare const SESSION_RULE_CLASSES: readonly ["read", "write", "send", "buy", "delete", "execute"];
|
|
18
|
+
export type SessionRuleClass = (typeof SESSION_RULE_CLASSES)[number];
|
|
19
|
+
/** One rule of a session, as the runtime keeps it. */
|
|
20
|
+
export interface SessionRule {
|
|
21
|
+
name: string;
|
|
22
|
+
decision: SessionRuleDecision;
|
|
23
|
+
classes?: string[];
|
|
24
|
+
kinds?: string[];
|
|
25
|
+
where?: 'inside' | 'outside' | 'any';
|
|
26
|
+
paths?: string[];
|
|
27
|
+
commands?: string[];
|
|
28
|
+
reason?: string | null;
|
|
29
|
+
}
|
|
30
|
+
/** One policy document in force, as the runtime answers it. */
|
|
31
|
+
export interface PolicyInForce {
|
|
32
|
+
scope: 'organization' | 'team' | 'session';
|
|
33
|
+
version?: number;
|
|
34
|
+
rules?: SessionRule[];
|
|
35
|
+
limits?: Record<string, {
|
|
36
|
+
soft: number;
|
|
37
|
+
hard: number;
|
|
38
|
+
} | null>;
|
|
39
|
+
}
|
|
40
|
+
/** What decides a session now (`GET /apps/sessions/{uid}/rules`). */
|
|
41
|
+
export interface RulesInForce {
|
|
42
|
+
uid: string;
|
|
43
|
+
harness: string | null;
|
|
44
|
+
managed?: boolean;
|
|
45
|
+
policies: PolicyInForce[];
|
|
46
|
+
session_rules: SessionRule[];
|
|
47
|
+
/** The sentence when nothing can be decided (SHIELD decision 11), else null. */
|
|
48
|
+
unavailable: string | null;
|
|
49
|
+
}
|
|
50
|
+
/** The words of the card's session section. */
|
|
51
|
+
export declare const SESSION_RULES_WORDS: {
|
|
52
|
+
readonly title: "This session";
|
|
53
|
+
readonly none: "No rule of your own on this session yet.";
|
|
54
|
+
readonly noSession: "Start a conversation to add a rule to its session.";
|
|
55
|
+
readonly add: "Add";
|
|
56
|
+
readonly remove: "Remove";
|
|
57
|
+
readonly namePlaceholder: "A name, quoted in every sentence it decides";
|
|
58
|
+
readonly decisions: Record<SessionRuleDecision, string>;
|
|
59
|
+
readonly classes: Record<SessionRuleClass, string>;
|
|
60
|
+
readonly scopes: Record<PolicyInForce["scope"], string>;
|
|
61
|
+
readonly goneWithSession: "In force at once, for this session only; gone when it ends.";
|
|
62
|
+
readonly unavailable: (sentence: string) => string;
|
|
63
|
+
};
|
|
64
|
+
/** A rule in words: *writing, sending: leave it to me*. */
|
|
65
|
+
export declare function sessionRuleInWords(rule: SessionRule): string;
|
|
66
|
+
/** What the person typed, as the rule the runtime takes; a sentence when it cannot be one. */
|
|
67
|
+
export declare function sessionRuleOf(input: {
|
|
68
|
+
name: string;
|
|
69
|
+
decision: string;
|
|
70
|
+
classes: string[];
|
|
71
|
+
}): SessionRule | string;
|
|
72
|
+
/** Where the session API answers from, for one session. */
|
|
73
|
+
export declare const sessionRulesUrl: (agentServerUrl: string, sessionUid: string) => string;
|
|
74
|
+
type Fetch = typeof fetch;
|
|
75
|
+
/** What decides the session now. */
|
|
76
|
+
export declare function readSessionRules(agentServerUrl: string, token: string, sessionUid: string, fetcher?: Fetch): Promise<RulesInForce>;
|
|
77
|
+
/** Add or tighten a rule on the session; the runtime answers what is in force now. */
|
|
78
|
+
export declare function addSessionRule(agentServerUrl: string, token: string, sessionUid: string, rule: SessionRule, fetcher?: Fetch): Promise<RulesInForce>;
|
|
79
|
+
/** Take a session rule back. */
|
|
80
|
+
export declare function removeSessionRule(agentServerUrl: string, token: string, sessionUid: string, name: string, fetcher?: Fetch): Promise<RulesInForce>;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* A rule a person adds to a running session (SHIELD.md §6.3, SH-54): the
|
|
7
|
+
* session API's `/apps/sessions/{uid}/rules`, read and written from the
|
|
8
|
+
* Rules card beside the page, and the words it says.
|
|
9
|
+
*
|
|
10
|
+
* The rule is the Shield's own shape (`@datalayer/agent-shield`'s `Rule`): a
|
|
11
|
+
* name, a decision — `allow`, `ask`, `deny` — and what it names: classes
|
|
12
|
+
* (read, write, send, buy, delete, execute), a harness's kinds, where, paths,
|
|
13
|
+
* commands. It may only tighten: one that would permit more than the
|
|
14
|
+
* organization's rules is refused by the runtime in a sentence, shown as is.
|
|
15
|
+
* The phone's panel speaks to the same three routes with the same shapes.
|
|
16
|
+
*
|
|
17
|
+
* @module apps/apps/sessionRules
|
|
18
|
+
*/
|
|
19
|
+
export const SESSION_RULE_DECISIONS = ['allow', 'ask', 'deny'];
|
|
20
|
+
export const SESSION_RULE_CLASSES = [
|
|
21
|
+
'read',
|
|
22
|
+
'write',
|
|
23
|
+
'send',
|
|
24
|
+
'buy',
|
|
25
|
+
'delete',
|
|
26
|
+
'execute',
|
|
27
|
+
];
|
|
28
|
+
/** The words of the card's session section. */
|
|
29
|
+
export const SESSION_RULES_WORDS = {
|
|
30
|
+
title: 'This session',
|
|
31
|
+
none: 'No rule of your own on this session yet.',
|
|
32
|
+
noSession: 'Start a conversation to add a rule to its session.',
|
|
33
|
+
add: 'Add',
|
|
34
|
+
remove: 'Remove',
|
|
35
|
+
namePlaceholder: 'A name, quoted in every sentence it decides',
|
|
36
|
+
decisions: {
|
|
37
|
+
allow: 'do it',
|
|
38
|
+
ask: 'ask me first',
|
|
39
|
+
deny: 'leave it to me',
|
|
40
|
+
},
|
|
41
|
+
classes: {
|
|
42
|
+
read: 'reading',
|
|
43
|
+
write: 'writing',
|
|
44
|
+
send: 'sending',
|
|
45
|
+
buy: 'buying',
|
|
46
|
+
delete: 'deleting',
|
|
47
|
+
execute: 'running a command',
|
|
48
|
+
},
|
|
49
|
+
scopes: {
|
|
50
|
+
organization: 'your organization',
|
|
51
|
+
team: 'this application',
|
|
52
|
+
session: 'this session',
|
|
53
|
+
},
|
|
54
|
+
goneWithSession: 'In force at once, for this session only; gone when it ends.',
|
|
55
|
+
unavailable: (sentence) => `Nothing is decided right now: ${sentence}`,
|
|
56
|
+
};
|
|
57
|
+
/** A rule in words: *writing, sending: leave it to me*. */
|
|
58
|
+
export function sessionRuleInWords(rule) {
|
|
59
|
+
const classes = (rule.classes ?? []).map(item => SESSION_RULES_WORDS.classes[item] ?? item);
|
|
60
|
+
const covers = classes.length > 0 ? classes.join(', ') : 'everything';
|
|
61
|
+
return `${covers}: ${SESSION_RULES_WORDS.decisions[rule.decision]}`;
|
|
62
|
+
}
|
|
63
|
+
/** What the person typed, as the rule the runtime takes; a sentence when it cannot be one. */
|
|
64
|
+
export function sessionRuleOf(input) {
|
|
65
|
+
const name = input.name.trim();
|
|
66
|
+
if (!name) {
|
|
67
|
+
return 'A rule needs a name: it is quoted in every sentence it decides.';
|
|
68
|
+
}
|
|
69
|
+
if (!SESSION_RULE_DECISIONS.includes(input.decision)) {
|
|
70
|
+
return `A rule says ${SESSION_RULE_DECISIONS.join(', ')}, not “${input.decision}”.`;
|
|
71
|
+
}
|
|
72
|
+
const classes = input.classes.filter(item => SESSION_RULE_CLASSES.includes(item));
|
|
73
|
+
return {
|
|
74
|
+
name,
|
|
75
|
+
decision: input.decision,
|
|
76
|
+
classes,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Where the session API answers from, for one session. */
|
|
80
|
+
export const sessionRulesUrl = (agentServerUrl, sessionUid) => `${agentServerUrl}/api/v1/apps/sessions/${encodeURIComponent(sessionUid)}/rules`;
|
|
81
|
+
function parsed(text) {
|
|
82
|
+
try {
|
|
83
|
+
return text ? JSON.parse(text) : null;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function answered(response, what) {
|
|
90
|
+
const body = parsed(await response.text());
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
const detail = body && typeof body === 'object' && 'detail' in body
|
|
93
|
+
? String(body.detail)
|
|
94
|
+
: `${what} (${response.status})`;
|
|
95
|
+
throw new Error(detail);
|
|
96
|
+
}
|
|
97
|
+
return body;
|
|
98
|
+
}
|
|
99
|
+
/** What decides the session now. */
|
|
100
|
+
export async function readSessionRules(agentServerUrl, token, sessionUid, fetcher = fetch) {
|
|
101
|
+
const response = await fetcher(sessionRulesUrl(agentServerUrl, sessionUid), {
|
|
102
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
103
|
+
});
|
|
104
|
+
return answered(response, 'The rules of the session could not be read');
|
|
105
|
+
}
|
|
106
|
+
/** Add or tighten a rule on the session; the runtime answers what is in force now. */
|
|
107
|
+
export async function addSessionRule(agentServerUrl, token, sessionUid, rule, fetcher = fetch) {
|
|
108
|
+
const response = await fetcher(sessionRulesUrl(agentServerUrl, sessionUid), {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: {
|
|
111
|
+
Authorization: `Bearer ${token}`,
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify(rule),
|
|
115
|
+
});
|
|
116
|
+
return answered(response, 'The rule could not be added');
|
|
117
|
+
}
|
|
118
|
+
/** Take a session rule back. */
|
|
119
|
+
export async function removeSessionRule(agentServerUrl, token, sessionUid, name, fetcher = fetch) {
|
|
120
|
+
const response = await fetcher(`${sessionRulesUrl(agentServerUrl, sessionUid)}/${encodeURIComponent(name)}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` } });
|
|
121
|
+
return answered(response, 'The rule could not be removed');
|
|
122
|
+
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { JSX } from 'react';
|
|
14
14
|
import type { AppRuleSpec, AppSpec } from '../../../types/agentspecs';
|
|
15
|
+
import { type LoopWorkspaceContext } from '../../core';
|
|
15
16
|
import { type Draft } from '../../apps/saved';
|
|
16
17
|
import { type ApprovalRecord } from '../../../hooks/useToolApprovals';
|
|
17
18
|
/** What the card says. */
|
|
@@ -50,7 +51,19 @@ export declare function approvalsOfApp(approvals: ApprovalRecord[], appId: strin
|
|
|
50
51
|
export declare function DraftShown({ draft }: {
|
|
51
52
|
draft: Draft;
|
|
52
53
|
}): JSX.Element;
|
|
53
|
-
|
|
54
|
+
/**
|
|
55
|
+
* The rules of the running session (SHIELD §6.3, SH-54): what decides it now,
|
|
56
|
+
* the rules the person added, and a rule to add — in force at once, gone with
|
|
57
|
+
* the session, never below the organization's.
|
|
58
|
+
*/
|
|
59
|
+
export declare function SessionRules({ agentServerUrl, sessionUid, token, }: {
|
|
60
|
+
agentServerUrl: string;
|
|
61
|
+
sessionUid: string;
|
|
62
|
+
token: string;
|
|
63
|
+
}): JSX.Element;
|
|
64
|
+
export declare function AppRulesCard({ app, workspace, }: {
|
|
54
65
|
app: AppSpec;
|
|
66
|
+
/** The workspace the card sits in, when the slot gives it: names the session running. */
|
|
67
|
+
workspace?: LoopWorkspaceContext;
|
|
55
68
|
}): JSX.Element;
|
|
56
69
|
export default AppRulesCard;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo } from 'react';
|
|
3
|
-
import { Button, Heading, Label, Text } from '@primer/react';
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { Button, Heading, Label, Select, Text, TextInput } from '@primer/react';
|
|
4
4
|
import { Box } from '@datalayer/primer-addons';
|
|
5
5
|
import { useIAMStore } from '@datalayer/core/lib/state/substates/IAMState';
|
|
6
|
+
import { agentServerOf } from '../../core';
|
|
6
7
|
import { BEHAVIOUR_WORDS, coverOf } from '../../apps/rules';
|
|
8
|
+
import { SESSION_RULES_WORDS, SESSION_RULE_CLASSES, SESSION_RULE_DECISIONS, addSessionRule, readSessionRules, removeSessionRule, sessionRuleInWords, sessionRuleOf, } from '../../apps/sessionRules';
|
|
7
9
|
import { SAVE_WORDS, draftOfApproval } from '../../apps/saved';
|
|
8
10
|
import { useApproveToolRequest, useRejectToolRequest, useToolApprovalsQuery, } from '../../../hooks/useToolApprovals';
|
|
9
11
|
/** What the card says. */
|
|
@@ -61,8 +63,57 @@ function Approvals({ app }) {
|
|
|
61
63
|
return (_jsxs(Box, { as: "li", py: 2, borderTop: "1px solid", borderColor: "border.muted", fontSize: 1, children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: approval.tool_name }), ruleOfApproval(approval) ? (_jsx(Text, { as: "p", sx: { m: 0, color: 'fg.muted', fontSize: 0 }, children: ruleOfApproval(approval) })) : null, draft ? _jsx(DraftShown, { draft: draft }) : null, _jsxs(Box, { display: "flex", gap: 2, mt: 1, children: [_jsx(Button, { size: "small", variant: "primary", disabled: approve.isPending, onClick: () => approve.mutate({ id: approval.id }), children: draft ? SAVE_WORDS.approve : APP_RULES_WORDS.approve }), _jsx(Button, { size: "small", disabled: reject.isPending, onClick: () => reject.mutate({ id: approval.id }), children: draft ? SAVE_WORDS.decline : APP_RULES_WORDS.reject })] })] }, approval.id));
|
|
62
64
|
}) }))] }));
|
|
63
65
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
/**
|
|
67
|
+
* The rules of the running session (SHIELD §6.3, SH-54): what decides it now,
|
|
68
|
+
* the rules the person added, and a rule to add — in force at once, gone with
|
|
69
|
+
* the session, never below the organization's.
|
|
70
|
+
*/
|
|
71
|
+
export function SessionRules({ agentServerUrl, sessionUid, token, }) {
|
|
72
|
+
const [inForce, setInForce] = useState(null);
|
|
73
|
+
const [problem, setProblem] = useState('');
|
|
74
|
+
const [name, setName] = useState('');
|
|
75
|
+
const [decision, setDecision] = useState('ask');
|
|
76
|
+
const [kind, setKind] = useState('send');
|
|
77
|
+
const [busy, setBusy] = useState(false);
|
|
78
|
+
const refresh = useCallback(() => {
|
|
79
|
+
let cancelled = false;
|
|
80
|
+
readSessionRules(agentServerUrl, token, sessionUid).then(value => !cancelled && setInForce(value), (error) => !cancelled &&
|
|
81
|
+
setProblem(error instanceof Error ? error.message : String(error)));
|
|
82
|
+
return () => {
|
|
83
|
+
cancelled = true;
|
|
84
|
+
};
|
|
85
|
+
}, [agentServerUrl, token, sessionUid]);
|
|
86
|
+
useEffect(refresh, [refresh]);
|
|
87
|
+
const act = async (work) => {
|
|
88
|
+
setBusy(true);
|
|
89
|
+
setProblem('');
|
|
90
|
+
try {
|
|
91
|
+
setInForce(await work());
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
setProblem(error instanceof Error ? error.message : String(error));
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
setBusy(false);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const add = () => {
|
|
101
|
+
const rule = sessionRuleOf({ name, decision, classes: [kind] });
|
|
102
|
+
if (typeof rule === 'string') {
|
|
103
|
+
setProblem(rule);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
void act(() => addSessionRule(agentServerUrl, token, sessionUid, rule)).then(() => setName(''));
|
|
107
|
+
};
|
|
108
|
+
return (_jsxs(Box, { "data-testid": "session-rules", mt: 3, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 1 }, children: SESSION_RULES_WORDS.title }), inForce?.unavailable ? (_jsx(Text, { as: "p", role: "alert", sx: { fontSize: 0, m: 0, mb: 1 }, children: SESSION_RULES_WORDS.unavailable(inForce.unavailable) })) : null, inForce && inForce.session_rules.length === 0 ? (_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: SESSION_RULES_WORDS.none })) : (_jsx(Box, { as: "ul", listStyle: "none", p: 0, m: 0, children: (inForce?.session_rules ?? []).map(rule => (_jsxs(Box, { as: "li", py: 1, fontSize: 1, display: "flex", gap: 2, alignItems: "center", children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: rule.name }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: sessionRuleInWords(rule) }), _jsx(Button, { size: "small", variant: "invisible", disabled: busy, onClick: () => void act(() => removeSessionRule(agentServerUrl, token, sessionUid, rule.name)), children: SESSION_RULES_WORDS.remove })] }, rule.name))) })), _jsxs(Box, { display: "flex", gap: 1, mt: 1, flexWrap: "wrap", alignItems: "center", children: [_jsx(TextInput, { size: "small", value: name, placeholder: SESSION_RULES_WORDS.namePlaceholder, "aria-label": "The rule's name", onChange: event => setName(event.target.value) }), _jsx(Select, { size: "small", value: kind, "aria-label": "What it covers", onChange: event => setKind(event.target.value), children: SESSION_RULE_CLASSES.map(item => (_jsx(Select.Option, { value: item, children: SESSION_RULES_WORDS.classes[item] }, item))) }), _jsx(Select, { size: "small", value: decision, "aria-label": "What it says", onChange: event => setDecision(event.target.value), children: SESSION_RULE_DECISIONS.map(item => (_jsx(Select.Option, { value: item, children: SESSION_RULES_WORDS.decisions[item] }, item))) }), _jsx(Button, { size: "small", disabled: busy, onClick: add, children: SESSION_RULES_WORDS.add })] }), problem ? (_jsx(Text, { as: "p", role: "alert", sx: { fontSize: 0, m: 0, mt: 1 }, children: problem })) : null, _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 1, mb: 0 }, children: SESSION_RULES_WORDS.goneWithSession })] }));
|
|
109
|
+
}
|
|
110
|
+
export function AppRulesCard({ app, workspace, }) {
|
|
111
|
+
const token = useIAMStore(state => state.token) ?? '';
|
|
112
|
+
const signedIn = Boolean(token);
|
|
113
|
+
const agentServerUrl = workspace
|
|
114
|
+
? agentServerOf(workspace.sandbox, workspace.serverUrl)
|
|
115
|
+
: undefined;
|
|
116
|
+
const sessionUid = workspace?.conversationId;
|
|
117
|
+
return (_jsxs(Box, { "data-testid": "app-rules", mb: 4, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 2 }, children: APP_RULES_WORDS.title }), app.rules.length === 0 ? (_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: APP_RULES_WORDS.none })) : (_jsx(Box, { as: "ul", listStyle: "none", p: 0, m: 0, children: app.rules.map(ruleInWords).map((rule, index) => (_jsxs(Box, { as: "li", py: 1, fontSize: 1, children: [_jsx(Text, { children: rule.action }), ' ', _jsx(Label, { title: rule.means, children: rule.says }), _jsx(Text, { as: "p", sx: { m: 0, color: 'fg.muted', fontSize: 0 }, children: rule.covers })] }, index))) })), _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 1, mb: 0 }, children: APP_RULES_WORDS.byDefault }), signedIn ? (_jsx(Approvals, { app: app })) : (_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', mt: 3, mb: 0 }, children: APP_RULES_WORDS.signedOut })), signedIn && agentServerUrl ? (sessionUid ? (_jsx(SessionRules, { agentServerUrl: agentServerUrl, sessionUid: sessionUid, token: token })) : (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 3, mb: 0 }, children: SESSION_RULES_WORDS.noSession }))) : null] }));
|
|
67
118
|
}
|
|
68
119
|
export default AppRulesCard;
|
|
@@ -3,5 +3,6 @@ import type { AppSpec } from '../../../types/agentspecs';
|
|
|
3
3
|
export declare const APP_RULES_PLUGIN_NAME = "@datalayer/loop-plugin-app-rules";
|
|
4
4
|
/** The plugin that lists an application's rules and the approvals waiting for the person. */
|
|
5
5
|
export declare function defineAppRulesPlugin(app: AppSpec): ReactorPlugin<Record<string, never>, unknown, unknown>;
|
|
6
|
-
export { AppRulesCard, APP_RULES_WORDS, ruleInWords, ruleOfApproval, approvalsOfApp, } from './AppRulesCard';
|
|
6
|
+
export { AppRulesCard, SessionRules, APP_RULES_WORDS, ruleInWords, ruleOfApproval, approvalsOfApp, } from './AppRulesCard';
|
|
7
|
+
export { SESSION_RULES_WORDS, sessionRuleInWords, sessionRuleOf, } from '../../apps/sessionRules';
|
|
7
8
|
export default defineAppRulesPlugin;
|
|
@@ -7,8 +7,8 @@ export const APP_RULES_PLUGIN_NAME = '@datalayer/loop-plugin-app-rules';
|
|
|
7
7
|
/** The plugin that lists an application's rules and the approvals waiting for the person. */
|
|
8
8
|
export function defineAppRulesPlugin(app) {
|
|
9
9
|
// One component per plugin: the slot keeps it, and the application with it.
|
|
10
|
-
function Card() {
|
|
11
|
-
return _jsx(AppRulesCard, { app: app });
|
|
10
|
+
function Card(props) {
|
|
11
|
+
return _jsx(AppRulesCard, { app: app, workspace: props.workspace });
|
|
12
12
|
}
|
|
13
13
|
const plugin = definePlugin({
|
|
14
14
|
name: `${APP_RULES_PLUGIN_NAME}-${app.id}`,
|
|
@@ -30,5 +30,6 @@ export function defineAppRulesPlugin(app) {
|
|
|
30
30
|
});
|
|
31
31
|
return plugin;
|
|
32
32
|
}
|
|
33
|
-
export { AppRulesCard, APP_RULES_WORDS, ruleInWords, ruleOfApproval, approvalsOfApp, } from './AppRulesCard';
|
|
33
|
+
export { AppRulesCard, SessionRules, APP_RULES_WORDS, ruleInWords, ruleOfApproval, approvalsOfApp, } from './AppRulesCard';
|
|
34
|
+
export { SESSION_RULES_WORDS, sessionRuleInWords, sessionRuleOf, } from '../../apps/sessionRules';
|
|
34
35
|
export default defineAppRulesPlugin;
|