@datalayer/agent-runtimes 1.3.55 → 1.3.57
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/lib/chat/base/ChatBase.js +8 -3
- package/lib/chat/index.d.ts +1 -0
- package/lib/chat/index.js +3 -0
- package/lib/chat/marks/SpecMark.d.ts +46 -0
- package/lib/chat/marks/SpecMark.js +90 -0
- package/lib/chat/marks/iconRef.d.ts +29 -0
- package/lib/chat/marks/iconRef.js +40 -0
- package/lib/chat/marks/index.d.ts +8 -0
- package/lib/chat/marks/index.js +12 -0
- package/lib/chat/marks/toolMarks.d.ts +43 -0
- package/lib/chat/marks/toolMarks.js +110 -0
- package/lib/chat/messages/ChatMessageList.d.ts +8 -1
- package/lib/chat/messages/ChatMessageList.js +11 -18
- package/lib/chat/parts/ToolPart.js +6 -1
- package/lib/chat/prompt/InputPrompt.d.ts +4 -1
- package/lib/chat/prompt/InputPrompt.js +2 -2
- package/lib/chat/prompt/menus/SkillsMenu.js +2 -1
- package/lib/chat/prompt/menus/ToolsMenu.d.ts +3 -1
- package/lib/chat/prompt/menus/ToolsMenu.js +25 -9
- package/lib/chat/tools/ToolCallDisplay.d.ts +8 -1
- package/lib/chat/tools/ToolCallDisplay.js +3 -2
- package/lib/loop/apps/appspec.js +17 -2
- package/lib/loop/plugins/chat/ChatView.js +7 -5
- package/lib/specs/actions.js +56 -0
- package/lib/specs/apps.js +239 -4
- package/lib/specs/appspecSchema.js +37 -1
- package/lib/specs/frontendTools.js +6 -6
- package/lib/specs/mcpServers.d.ts +1 -0
- package/lib/specs/mcpServers.js +39 -16
- package/lib/specs/skills.js +7 -7
- package/lib/specs/tools.js +21 -21
- package/lib/types/agentspecs.d.ts +11 -0
- package/lib/types/chat.d.ts +4 -0
- package/lib/types/mcp.d.ts +2 -2
- package/lib/types/skills.d.ts +2 -2
- package/lib/types/tools.d.ts +4 -4
- package/package.json +1 -1
- package/scripts/codegen/agentspecs_clone.py +5 -3
- package/scripts/codegen/generate_frontend_tools.py +2 -0
- package/scripts/codegen/generate_mcp_servers.py +2 -0
- package/scripts/codegen/generate_skills.py +2 -0
- package/scripts/codegen/generate_tools.py +2 -0
- package/scripts/codegen/marks.py +33 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BuiltinTool, MCPServerConfig } from '../../../types';
|
|
2
|
-
export declare function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, availableTools, }: {
|
|
2
|
+
export declare function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, availableTools, availableFrontendTools, }: {
|
|
3
3
|
codemodeEnabled: boolean;
|
|
4
4
|
onToggleCodemode?: (enabled: boolean) => void | Promise<void>;
|
|
5
5
|
mcpServers: MCPServerConfig[];
|
|
@@ -10,4 +10,6 @@ export declare function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServer
|
|
|
10
10
|
approvedMcpTools: Map<string, Set<string>>;
|
|
11
11
|
onToggleMcpToolApproval: (serverId: string, toolName: string) => void;
|
|
12
12
|
availableTools: BuiltinTool[];
|
|
13
|
+
/** The frontend tools: the ones the page runs for the agent. */
|
|
14
|
+
availableFrontendTools?: BuiltinTool[];
|
|
13
15
|
}): import("react").JSX.Element;
|
|
@@ -4,14 +4,20 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
|
-
* What the agent may call:
|
|
7
|
+
* What the agent may call: the runtime's tools, the frontend tools (the ones
|
|
8
|
+
* the page runs), MCP servers, and codemode — each drawn with its mark.
|
|
8
9
|
*
|
|
9
10
|
* @module chat/prompt/menus/ToolsMenu
|
|
10
11
|
*/
|
|
11
12
|
import { Text, Button, ActionMenu, ActionList, ToggleSwitch, Tooltip, } from '@primer/react';
|
|
12
13
|
import { Box } from '@datalayer/primer-addons';
|
|
13
14
|
import { ToolsIcon } from '@primer/octicons-react';
|
|
14
|
-
|
|
15
|
+
import { SpecMark, hasMark, marksOfFrontendTool, marksOfMcpServer, marksOfRuntimeTool, } from '../../marks';
|
|
16
|
+
/** A tool's mark, as the leading visual of its row. */
|
|
17
|
+
function LeadingMark({ marks }) {
|
|
18
|
+
return hasMark(marks) ? (_jsx(ActionList.LeadingVisual, { children: _jsx(SpecMark, { icon: marks.icon, emoji: marks.emoji, size: 16 }) })) : null;
|
|
19
|
+
}
|
|
20
|
+
export function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabledMcpTools, enabledMcpToolCount, onToggleMcpTool, onToggleAllMcpServerTools, approvedMcpTools, onToggleMcpToolApproval, availableTools, availableFrontendTools = [], }) {
|
|
15
21
|
const hasUsableMcpServers = mcpServers.some(server => server.isAvailable);
|
|
16
22
|
/*
|
|
17
23
|
* A count, not a word.
|
|
@@ -23,12 +29,17 @@ export function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabl
|
|
|
23
29
|
*/
|
|
24
30
|
const summary = [
|
|
25
31
|
`${availableTools.length} tool${availableTools.length === 1 ? '' : 's'}`,
|
|
32
|
+
availableFrontendTools.length > 0
|
|
33
|
+
? `${availableFrontendTools.length} frontend tool${availableFrontendTools.length === 1 ? '' : 's'}`
|
|
34
|
+
: null,
|
|
26
35
|
enabledMcpToolCount > 0 ? `${enabledMcpToolCount} MCP enabled` : null,
|
|
27
36
|
hasUsableMcpServers ? null : 'no MCP server available',
|
|
28
37
|
]
|
|
29
38
|
.filter(Boolean)
|
|
30
39
|
.join(' · ');
|
|
31
|
-
return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Tooltip, { text: `Tools — ${summary}`, direction: "n", children: _jsx(Button, { type: "button", variant: "invisible", size: "small", "aria-label": `Tools — ${summary}`, leadingVisual: ToolsIcon, children: _jsx(Text, { sx: { fontSize: 0 }, children: availableTools.length +
|
|
40
|
+
return (_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Anchor, { children: _jsx(Tooltip, { text: `Tools — ${summary}`, direction: "n", children: _jsx(Button, { type: "button", variant: "invisible", size: "small", "aria-label": `Tools — ${summary}`, leadingVisual: ToolsIcon, children: _jsx(Text, { sx: { fontSize: 0 }, children: availableTools.length +
|
|
41
|
+
availableFrontendTools.length +
|
|
42
|
+
enabledMcpToolCount }) }) }) }), _jsx(ActionMenu.Overlay, { side: "outside-top", align: "start", width: "large", children: _jsx(Box, { sx: { maxHeight: '60vh', overflowY: 'auto' }, children: _jsxs(ActionList, { children: [_jsx(ActionList.Group, { title: "Codemode", children: _jsxs(Box, { sx: {
|
|
32
43
|
display: 'flex',
|
|
33
44
|
alignItems: 'center',
|
|
34
45
|
justifyContent: 'space-between',
|
|
@@ -43,12 +54,13 @@ export function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabl
|
|
|
43
54
|
if (onToggleCodemode) {
|
|
44
55
|
void onToggleCodemode(!codemodeEnabled);
|
|
45
56
|
}
|
|
46
|
-
}, "aria-labelledby": "toggle-codemode" })] }) }), availableTools.length > 0 ? (_jsx(ActionList.Group, { title: "Tools", children: availableTools.map(tool => (_jsx(ActionList.Item, { disabled: true, children: tool.name }, tool.id))) })) : null, mcpServers.length > 0 && hasUsableMcpServers ? (mcpServers.map(server => {
|
|
57
|
+
}, "aria-labelledby": "toggle-codemode" })] }) }), availableTools.length > 0 ? (_jsx(ActionList.Group, { title: "Tools", children: availableTools.map(tool => (_jsxs(ActionList.Item, { disabled: true, children: [_jsx(LeadingMark, { marks: marksOfRuntimeTool(tool.name) }), tool.name] }, tool.id))) })) : null, availableFrontendTools.length > 0 ? (_jsx(ActionList.Group, { title: "Frontend tools", children: availableFrontendTools.map(tool => (_jsxs(ActionList.Item, { disabled: true, children: [_jsx(LeadingMark, { marks: marksOfFrontendTool(tool.name) }), tool.name] }, tool.id))) })) : null, mcpServers.length > 0 && hasUsableMcpServers ? (mcpServers.map(server => {
|
|
47
58
|
const serverTools = enabledMcpTools.get(server.id);
|
|
48
59
|
const allToolNames = server.tools.map(t => t.name);
|
|
49
60
|
const enabledCount = serverTools?.size ?? 0;
|
|
50
61
|
const allEnabled = enabledCount === allToolNames.length &&
|
|
51
62
|
allToolNames.length > 0;
|
|
63
|
+
const serverMarks = marksOfMcpServer(server);
|
|
52
64
|
return (_jsxs(ActionList.Group, { title: `${server.name}${server.isAvailable ? '' : ' (unavailable)'}`, children: [server.isAvailable && server.tools.length > 0 && (_jsxs(Box, { sx: {
|
|
53
65
|
display: 'flex',
|
|
54
66
|
alignItems: 'center',
|
|
@@ -57,11 +69,15 @@ export function ToolsMenu({ codemodeEnabled, onToggleCodemode, mcpServers, enabl
|
|
|
57
69
|
py: 2,
|
|
58
70
|
borderBottom: '1px solid',
|
|
59
71
|
borderColor: 'border.muted',
|
|
60
|
-
}, children: [_jsxs(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}, children: [
|
|
72
|
+
}, children: [_jsxs(Box, { sx: {
|
|
73
|
+
display: 'flex',
|
|
74
|
+
alignItems: 'center',
|
|
75
|
+
gap: 2,
|
|
76
|
+
}, children: [hasMark(serverMarks) && (_jsx(SpecMark, { icon: serverMarks.icon, emoji: serverMarks.emoji, size: 16 })), _jsxs(Text, { id: `toggle-all-${server.id}`, sx: {
|
|
77
|
+
fontSize: 0,
|
|
78
|
+
fontWeight: 'semibold',
|
|
79
|
+
color: 'fg.muted',
|
|
80
|
+
}, children: ["Enable all (", enabledCount, "/", allToolNames.length, ")"] })] }), _jsx(ToggleSwitch, { size: "small", checked: allEnabled, onClick: () => onToggleAllMcpServerTools(server.id, allToolNames, !allEnabled), "aria-labelledby": `toggle-all-${server.id}` })] })), server.isAvailable && server.tools.length > 0 ? (server.tools.map(tool => {
|
|
65
81
|
const isEnabled = serverTools?.has(tool.name) ?? false;
|
|
66
82
|
const serverApproved = approvedMcpTools.get(server.id);
|
|
67
83
|
// Tools default to NOT approved — user must explicitly
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import type { CodeError, ExecutionResult, DisplayToolCallStatus } from '../../types';
|
|
9
|
+
import { type Marks } from '../marks';
|
|
9
10
|
/**
|
|
10
11
|
* Error type classification for display purposes
|
|
11
12
|
*/
|
|
@@ -43,6 +44,12 @@ export interface ToolCallDisplayProps {
|
|
|
43
44
|
onDeny?: () => void;
|
|
44
45
|
/** Loading state for approval actions */
|
|
45
46
|
approvalLoading?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The marks of whoever the tool belongs to — its MCP server, skill,
|
|
49
|
+
* frontend tool set or runtime tool spec — drawn before its name: the
|
|
50
|
+
* icon, else the emoji, else nothing.
|
|
51
|
+
*/
|
|
52
|
+
marks?: Marks | null;
|
|
46
53
|
}
|
|
47
54
|
/**
|
|
48
55
|
* ToolCallDisplay component - Default display for tool calls in chat
|
|
@@ -54,5 +61,5 @@ export interface ToolCallDisplayProps {
|
|
|
54
61
|
* - Color-coded status indicators
|
|
55
62
|
* - Rich error display distinguishing execution errors from code errors
|
|
56
63
|
*/
|
|
57
|
-
export declare function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading, }: ToolCallDisplayProps): React.JSX.Element;
|
|
64
|
+
export declare function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading, marks, }: ToolCallDisplayProps): React.JSX.Element;
|
|
58
65
|
export default ToolCallDisplay;
|
|
@@ -13,6 +13,7 @@ import { useEffect, useState } from 'react';
|
|
|
13
13
|
import { Button, Text } from '@primer/react';
|
|
14
14
|
import { Box } from '@datalayer/primer-addons';
|
|
15
15
|
import { ChevronDownIcon, ChevronRightIcon, ToolsIcon, CheckCircleIcon, XCircleIcon, ClockIcon, AlertIcon, } from '@primer/octicons-react';
|
|
16
|
+
import { SpecMark, hasMark } from '../marks';
|
|
16
17
|
/**
|
|
17
18
|
* Get status icon and color based on tool call status
|
|
18
19
|
*/
|
|
@@ -124,7 +125,7 @@ function getArgsSummary(args) {
|
|
|
124
125
|
* - Color-coded status indicators
|
|
125
126
|
* - Rich error display distinguishing execution errors from code errors
|
|
126
127
|
*/
|
|
127
|
-
export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading = false, }) {
|
|
128
|
+
export function ToolCallDisplay({ toolCallId, toolName, args, result, status, error, executionResult, codeError, exitCode, executionError, approvalRequired = false, approvalState, approvalDecisionSource, onApprove, onDeny, approvalLoading = false, marks, }) {
|
|
128
129
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
129
130
|
// Determine effective exit code from props or execution result
|
|
130
131
|
const effectiveExitCode = exitCode ?? executionResult?.exit_code;
|
|
@@ -189,7 +190,7 @@ export function ToolCallDisplay({ toolCallId, toolName, args, result, status, er
|
|
|
189
190
|
'&:hover': {
|
|
190
191
|
backgroundColor: 'neutral.muted',
|
|
191
192
|
},
|
|
192
|
-
}, children: [_jsx(Box, { sx: { color: 'fg.muted', flexShrink: 0 }, children: isExpanded ? (_jsx(ChevronDownIcon, { size: 16 })) : (_jsx(ChevronRightIcon, { size: 16 })) }), _jsx(Box, { sx: { color: 'fg.muted', flexShrink: 0 }, children: _jsx(
|
|
193
|
+
}, children: [_jsx(Box, { sx: { color: 'fg.muted', flexShrink: 0 }, children: isExpanded ? (_jsx(ChevronDownIcon, { size: 16 })) : (_jsx(ChevronRightIcon, { size: 16 })) }), hasMark(marks) && (_jsx(Box, { sx: { color: 'fg.muted', flexShrink: 0, display: 'flex' }, children: _jsx(SpecMark, { icon: marks?.icon, emoji: marks?.emoji, size: 16 }) })), _jsx(Text, { sx: {
|
|
193
194
|
fontWeight: 'semibold',
|
|
194
195
|
fontSize: 1,
|
|
195
196
|
color: 'fg.default',
|
package/lib/loop/apps/appspec.js
CHANGED
|
@@ -106,7 +106,12 @@ export function emptyAppspec(kind = 'chat') {
|
|
|
106
106
|
settings: [],
|
|
107
107
|
components: [],
|
|
108
108
|
},
|
|
109
|
-
tests: {
|
|
109
|
+
tests: {
|
|
110
|
+
readyAt: DEFAULT_READY_AT,
|
|
111
|
+
evalset: '',
|
|
112
|
+
cases: [],
|
|
113
|
+
verified: { live: [], recorded: [], unverified: [] },
|
|
114
|
+
},
|
|
110
115
|
record: {
|
|
111
116
|
keepFor: DEFAULT_KEEP_FOR,
|
|
112
117
|
retentionDays: retentionDays(DEFAULT_KEEP_FOR),
|
|
@@ -315,6 +320,7 @@ export function parseAppspec(document) {
|
|
|
315
320
|
const permissions = isData(data.permissions) ? data.permissions : {};
|
|
316
321
|
const computer = isData(permissions.computer) ? permissions.computer : {};
|
|
317
322
|
const tests = isData(data.tests) ? data.tests : {};
|
|
323
|
+
const verified = isData(tests.verified) ? tests.verified : {};
|
|
318
324
|
const record = isData(data.record) ? data.record : {};
|
|
319
325
|
const checks = isData(data.checks) ? data.checks : {};
|
|
320
326
|
const keepFor = text(record.keep_for, DEFAULT_KEEP_FOR);
|
|
@@ -359,6 +365,11 @@ export function parseAppspec(document) {
|
|
|
359
365
|
ask: text(testCase.ask),
|
|
360
366
|
expect: text(testCase.expect),
|
|
361
367
|
})),
|
|
368
|
+
verified: {
|
|
369
|
+
live: texts(verified.live),
|
|
370
|
+
recorded: texts(verified.recorded),
|
|
371
|
+
unverified: texts(verified.unverified),
|
|
372
|
+
},
|
|
362
373
|
},
|
|
363
374
|
record: {
|
|
364
375
|
keepFor,
|
|
@@ -559,7 +570,11 @@ export function dumpAppspec(app) {
|
|
|
559
570
|
.list('cases', app.tests.cases.map(testCase => ({
|
|
560
571
|
ask: testCase.ask,
|
|
561
572
|
expect: testCase.expect,
|
|
562
|
-
})))
|
|
573
|
+
})))
|
|
574
|
+
.part('verified', new Writer()
|
|
575
|
+
.list('live', app.tests.verified.live)
|
|
576
|
+
.list('recorded', app.tests.verified.recorded)
|
|
577
|
+
.list('unverified', app.tests.verified.unverified).data).data)
|
|
563
578
|
.part('record', new Writer()
|
|
564
579
|
.text('keep_for', app.record.keepFor, DEFAULT_KEEP_FOR)
|
|
565
580
|
.list('include', app.record.include, DEFAULT_RECORD_INCLUDE)
|
|
@@ -1288,12 +1288,13 @@ export default function ChatView({ workspace }) {
|
|
|
1288
1288
|
const offeredTools = useMemo(() => {
|
|
1289
1289
|
const fromServer = configQuery.data?.builtinTools ?? [];
|
|
1290
1290
|
const seen = new Set(fromServer.map(tool => tool.name));
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1291
|
+
// The runtime's, and the frontend tools this page runs: named apart.
|
|
1292
|
+
return {
|
|
1293
|
+
runtime: fromServer,
|
|
1294
|
+
frontend: agentTools
|
|
1294
1295
|
.filter(tool => !seen.has(tool.name))
|
|
1295
1296
|
.map(tool => ({ id: tool.name, name: tool.name })),
|
|
1296
|
-
|
|
1297
|
+
};
|
|
1297
1298
|
}, [configQuery.data?.builtinTools, agentTools]);
|
|
1298
1299
|
/* Which skills are on, as the runtime last reported them. Derived rather
|
|
1299
1300
|
than held: the source of truth is the agent, and a local copy would drift
|
|
@@ -1423,7 +1424,8 @@ export default function ChatView({ workspace }) {
|
|
|
1423
1424
|
selectedModel: activeModel,
|
|
1424
1425
|
onModelSelect: model => void selectModel(model),
|
|
1425
1426
|
showToolsMenu: !presence,
|
|
1426
|
-
availableTools: offeredTools,
|
|
1427
|
+
availableTools: offeredTools.runtime,
|
|
1428
|
+
availableFrontendTools: offeredTools.frontend,
|
|
1427
1429
|
mcpServers: configQuery.data?.mcpServers ?? [],
|
|
1428
1430
|
// Live from the host example, when one feeds it: the footer's MCP status
|
|
1429
1431
|
// indicator. (Codemode surfaces through the toggle below, not a blob.)
|
package/lib/specs/actions.js
CHANGED
|
@@ -547,6 +547,62 @@ export const SERVER_ACTIONS = {
|
|
|
547
547
|
tools: {},
|
|
548
548
|
conditions: {},
|
|
549
549
|
},
|
|
550
|
+
'odoo-accounting': {
|
|
551
|
+
checked: '2026-10-05',
|
|
552
|
+
default: [],
|
|
553
|
+
tools: {
|
|
554
|
+
odoo_accounting_list_invoices: ['read'],
|
|
555
|
+
odoo_accounting_get_invoice: ['read'],
|
|
556
|
+
odoo_accounting_list_journal_entries: ['read'],
|
|
557
|
+
odoo_accounting_list_open_balances: ['read'],
|
|
558
|
+
odoo_accounting_list_accounts: ['read'],
|
|
559
|
+
odoo_accounting_list_journals: ['read'],
|
|
560
|
+
odoo_accounting_get_journal_entry: ['read'],
|
|
561
|
+
odoo_accounting_trial_balance: ['read'],
|
|
562
|
+
odoo_accounting_general_ledger: ['read'],
|
|
563
|
+
odoo_accounting_create_draft_invoice: ['write'],
|
|
564
|
+
odoo_accounting_post_invoice: ['write'],
|
|
565
|
+
odoo_accounting_create_draft_journal_entry: ['write'],
|
|
566
|
+
odoo_accounting_post_journal_entry: ['write'],
|
|
567
|
+
odoo_accounting_list_partners: ['read'],
|
|
568
|
+
odoo_accounting_partner_ledger: ['read'],
|
|
569
|
+
odoo_accounting_aged_balance: ['read'],
|
|
570
|
+
odoo_accounting_list_taxes: ['read'],
|
|
571
|
+
odoo_accounting_list_assets: ['read'],
|
|
572
|
+
odoo_accounting_get_asset: ['read'],
|
|
573
|
+
odoo_accounting_reconcile_lines: ['write'],
|
|
574
|
+
odoo_accounting_unreconcile_lines: ['write'],
|
|
575
|
+
odoo_accounting_bank_status: ['read'],
|
|
576
|
+
odoo_accounting_list_bank_lines: ['read'],
|
|
577
|
+
odoo_accounting_get_bank_line: ['read'],
|
|
578
|
+
odoo_accounting_suggest_bank_matches: ['read'],
|
|
579
|
+
odoo_accounting_suggest_reconciliations: ['read'],
|
|
580
|
+
odoo_accounting_explain_account_balance: ['read'],
|
|
581
|
+
odoo_accounting_list_bank_feeds: ['read'],
|
|
582
|
+
odoo_accounting_list_currency_rates: ['read'],
|
|
583
|
+
odoo_accounting_get_lock_dates: ['read'],
|
|
584
|
+
odoo_accounting_book_bank_line: ['write'],
|
|
585
|
+
odoo_accounting_match_bank_line: ['write'],
|
|
586
|
+
odoo_accounting_reset_bank_line: ['write'],
|
|
587
|
+
odoo_accounting_remove_duplicate_bank_lines: ['delete'],
|
|
588
|
+
odoo_accounting_link_bank_feed: ['write'],
|
|
589
|
+
odoo_accounting_create_vendor_bill: ['write'],
|
|
590
|
+
odoo_accounting_create_customer_invoice: ['write'],
|
|
591
|
+
odoo_accounting_set_currency_rates: ['write'],
|
|
592
|
+
odoo_accounting_set_lock_date: ['write'],
|
|
593
|
+
odoo_accounting_create_matching_model: ['write'],
|
|
594
|
+
odoo_accounting_get_tax_settings: ['read'],
|
|
595
|
+
odoo_accounting_list_tax_returns: ['read'],
|
|
596
|
+
odoo_accounting_get_tax_return: ['read'],
|
|
597
|
+
odoo_accounting_tax_grids: ['read'],
|
|
598
|
+
odoo_accounting_list_tax_grid_lines: ['read'],
|
|
599
|
+
odoo_accounting_check_tax_period: ['read'],
|
|
600
|
+
odoo_accounting_list_untagged_tax_lines: ['read'],
|
|
601
|
+
odoo_accounting_set_tax_periodicity: ['write'],
|
|
602
|
+
odoo_accounting_set_tax_grids: ['write'],
|
|
603
|
+
},
|
|
604
|
+
conditions: {},
|
|
605
|
+
},
|
|
550
606
|
salesforce: {
|
|
551
607
|
default: [],
|
|
552
608
|
tools: {},
|