agentix-cli 0.16.0 → 0.17.0
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/agent-4AOMVXRJ.js +2 -0
- package/dist/board-dashboard-CXIVJKDP.js +7282 -0
- package/dist/board-dashboard-CXIVJKDP.js.map +1 -0
- package/dist/chunk-34NG7UDX.js +11 -0
- package/dist/chunk-34NG7UDX.js.map +1 -0
- package/dist/chunk-4HP6UC2X.js +13 -0
- package/dist/chunk-4HP6UC2X.js.map +1 -0
- package/dist/chunk-5WNGHDFC.js +164 -0
- package/dist/chunk-5WNGHDFC.js.map +1 -0
- package/dist/{chunk-7MBTMCKY.js → chunk-63UYRJIC.js} +2 -2
- package/dist/chunk-6PPIFDOQ.js +1742 -0
- package/dist/chunk-6PPIFDOQ.js.map +1 -0
- package/dist/chunk-ABCHHNG6.js +625 -0
- package/dist/chunk-ABCHHNG6.js.map +1 -0
- package/dist/chunk-AFRHKA7B.js +2 -0
- package/dist/chunk-AFRHKA7B.js.map +1 -0
- package/dist/chunk-CDNWCYF7.js +2 -0
- package/dist/chunk-CDNWCYF7.js.map +1 -0
- package/dist/{chunk-6MKAXEE5.js → chunk-EKTPCSN4.js} +2 -2
- package/dist/{chunk-6MKAXEE5.js.map → chunk-EKTPCSN4.js.map} +1 -1
- package/dist/chunk-EW27SCCC.js +2 -0
- package/dist/chunk-EW27SCCC.js.map +1 -0
- package/dist/chunk-HCFSHGK4.js +46 -0
- package/dist/chunk-HCFSHGK4.js.map +1 -0
- package/dist/chunk-HHJGKD5B.js +71 -0
- package/dist/chunk-HHJGKD5B.js.map +1 -0
- package/dist/{chunk-YI2T5QYB.js → chunk-MBEQASP3.js} +2 -2
- package/dist/chunk-N67JZAXU.js +2 -0
- package/dist/chunk-N67JZAXU.js.map +1 -0
- package/dist/{chunk-FLOGK2U7.js → chunk-SRHLXZRF.js} +2 -2
- package/dist/chunk-TT2Q7YMZ.js +118 -0
- package/dist/chunk-TT2Q7YMZ.js.map +1 -0
- package/dist/{chunk-HI24KAEY.js → chunk-WJXU5F4Z.js} +3 -4
- package/dist/{chunk-HI24KAEY.js.map → chunk-WJXU5F4Z.js.map} +1 -1
- package/dist/chunk-XDJSYQST.js +6 -0
- package/dist/chunk-XDJSYQST.js.map +1 -0
- package/dist/chunk-YPOELN6Z.js +798 -0
- package/dist/chunk-YPOELN6Z.js.map +1 -0
- package/dist/{chunk-QZP65I2H.js → chunk-ZE2YFX4K.js} +2 -2
- package/dist/cli.js +1 -320
- package/dist/cli.js.map +1 -1
- package/dist/{compaction-JBZZ7I7Y.js → compaction-X46EQEPS.js} +6 -6
- package/dist/compaction-X46EQEPS.js.map +1 -0
- package/dist/{config-LN6JEHMF.js → config-KCYHMKCT.js} +2 -2
- package/dist/config-mutator-QP4GLBOE.js +2 -0
- package/dist/context-planner-G2J7FNNU.js +17 -0
- package/dist/context-planner-G2J7FNNU.js.map +1 -0
- package/dist/editor-chat-R54E65W5.js +137 -0
- package/dist/editor-chat-R54E65W5.js.map +1 -0
- package/dist/heal-JDXUPRET.js +2 -0
- package/dist/inbox-L5ZZ623Y.js +315 -0
- package/dist/inbox-L5ZZ623Y.js.map +1 -0
- package/dist/index.d.ts +2917 -1781
- package/dist/index.js +23 -53
- package/dist/index.js.map +1 -1
- package/dist/ingest-whatsapp-NS4OWDOU.js +6 -0
- package/dist/ingest-whatsapp-NS4OWDOU.js.map +1 -0
- package/dist/memory-extract-WH4FZ456.js +2 -0
- package/dist/processes-XF5CV4LK.js +256 -0
- package/dist/processes-XF5CV4LK.js.map +1 -0
- package/dist/program-FFWEILAS.js +2 -0
- package/dist/providers-AKQ4HTB4.js +2 -0
- package/dist/registry-IFMDJWQ7.js +2 -0
- package/dist/scheduler-63D5KFO7.js +2 -0
- package/dist/slack-PSQLVTGB.js +3 -0
- package/dist/slack-PSQLVTGB.js.map +1 -0
- package/dist/store-5MJOO74U.js +2 -0
- package/dist/store-5MJOO74U.js.map +1 -0
- package/dist/task-store-NM7VKNLE.js +2 -0
- package/dist/task-store-NM7VKNLE.js.map +1 -0
- package/dist/telegram-W4SLFMNY.js +3 -0
- package/dist/telegram-W4SLFMNY.js.map +1 -0
- package/dist/timers-PCB4ZIBD.js +2 -0
- package/dist/timers-PCB4ZIBD.js.map +1 -0
- package/dist/types-C7IFH42Z.js +2 -0
- package/dist/types-C7IFH42Z.js.map +1 -0
- package/dist/usage-dashboard-AXPXB2KP.js +803 -0
- package/dist/usage-dashboard-AXPXB2KP.js.map +1 -0
- package/dist/web/workflow-editor.global.js +1427 -0
- package/dist/web/workflow-editor.global.js.map +1 -0
- package/dist/whatsapp-DCHRBRVV.js +3 -0
- package/dist/whatsapp-DCHRBRVV.js.map +1 -0
- package/dist/workspace-setup-C4VB3QZV.js +2 -0
- package/dist/workspace-setup-C4VB3QZV.js.map +1 -0
- package/package.json +9 -2
- package/dist/agent-BCDPSPKU.js +0 -2
- package/dist/board-dashboard-LA7WW56M.js +0 -5668
- package/dist/board-dashboard-LA7WW56M.js.map +0 -1
- package/dist/chunk-6U2XOQHU.js +0 -7
- package/dist/chunk-6U2XOQHU.js.map +0 -1
- package/dist/chunk-7FJQGD6U.js +0 -6
- package/dist/chunk-7FJQGD6U.js.map +0 -1
- package/dist/chunk-ABDP7TDL.js +0 -71
- package/dist/chunk-ABDP7TDL.js.map +0 -1
- package/dist/chunk-CXY2RYNI.js +0 -11
- package/dist/chunk-CXY2RYNI.js.map +0 -1
- package/dist/chunk-HVC6FJNP.js +0 -108
- package/dist/chunk-HVC6FJNP.js.map +0 -1
- package/dist/chunk-K7BE4E35.js +0 -138
- package/dist/chunk-K7BE4E35.js.map +0 -1
- package/dist/chunk-KXJSLLSQ.js +0 -199
- package/dist/chunk-KXJSLLSQ.js.map +0 -1
- package/dist/chunk-KXZMYLHQ.js +0 -46
- package/dist/chunk-KXZMYLHQ.js.map +0 -1
- package/dist/chunk-M7HKBG3V.js +0 -2
- package/dist/chunk-M7HKBG3V.js.map +0 -1
- package/dist/chunk-RB7265LO.js +0 -12
- package/dist/chunk-RB7265LO.js.map +0 -1
- package/dist/compaction-JBZZ7I7Y.js.map +0 -1
- package/dist/config-mutator-24TH7PHM.js +0 -2
- package/dist/heal-WKY5I4KB.js +0 -2
- package/dist/memory-extract-AD7KMRPC.js +0 -2
- package/dist/providers-VUIWO3ZK.js +0 -2
- package/dist/registry-ASC2QS5K.js +0 -2
- package/dist/scheduler-A3TQOCKT.js +0 -2
- package/dist/usage-dashboard-QX3CF6KK.js +0 -404
- package/dist/usage-dashboard-QX3CF6KK.js.map +0 -1
- package/dist/workspace-setup-ZWTT42XT.js +0 -2
- /package/dist/{agent-BCDPSPKU.js.map → agent-4AOMVXRJ.js.map} +0 -0
- /package/dist/{chunk-7MBTMCKY.js.map → chunk-63UYRJIC.js.map} +0 -0
- /package/dist/{chunk-YI2T5QYB.js.map → chunk-MBEQASP3.js.map} +0 -0
- /package/dist/{chunk-FLOGK2U7.js.map → chunk-SRHLXZRF.js.map} +0 -0
- /package/dist/{chunk-QZP65I2H.js.map → chunk-ZE2YFX4K.js.map} +0 -0
- /package/dist/{config-LN6JEHMF.js.map → config-KCYHMKCT.js.map} +0 -0
- /package/dist/{config-mutator-24TH7PHM.js.map → config-mutator-QP4GLBOE.js.map} +0 -0
- /package/dist/{heal-WKY5I4KB.js.map → heal-JDXUPRET.js.map} +0 -0
- /package/dist/{memory-extract-AD7KMRPC.js.map → memory-extract-WH4FZ456.js.map} +0 -0
- /package/dist/{providers-VUIWO3ZK.js.map → program-FFWEILAS.js.map} +0 -0
- /package/dist/{registry-ASC2QS5K.js.map → providers-AKQ4HTB4.js.map} +0 -0
- /package/dist/{scheduler-A3TQOCKT.js.map → registry-IFMDJWQ7.js.map} +0 -0
- /package/dist/{workspace-setup-ZWTT42XT.js.map → scheduler-63D5KFO7.js.map} +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import{a,b as t}from"./chunk-6PPIFDOQ.js";import"./chunk-FIOB3MEX.js";function s(e={}){let o=`<div class="ax-inbox__root" data-actor="${t(e.actor??"")}">
|
|
2
|
+
<aside class="ax-inbox__list">
|
|
3
|
+
<header>
|
|
4
|
+
<h2>Inbox</h2>
|
|
5
|
+
<button id="inbox-refresh" class="ax-inbox__icon" title="Refresh (r)">\u21BB</button>
|
|
6
|
+
</header>
|
|
7
|
+
<div class="ax-inbox__actor">
|
|
8
|
+
<label>Actor <input id="inbox-actor" type="text" placeholder="actor:<id>" value="${t(e.actor??"")}" autocomplete="off" /></label>
|
|
9
|
+
</div>
|
|
10
|
+
<ul id="inbox-tasks" class="ax-inbox__cards" aria-live="polite"></ul>
|
|
11
|
+
<div id="inbox-empty" class="ax-inbox__empty" hidden>
|
|
12
|
+
<p>No open tasks.</p>
|
|
13
|
+
<p class="hint">Set the actor filter to see tasks assigned to you, or leave blank for all tasks in the system.</p>
|
|
14
|
+
</div>
|
|
15
|
+
</aside>
|
|
16
|
+
|
|
17
|
+
<section class="ax-inbox__detail">
|
|
18
|
+
<header id="inbox-detail-head">
|
|
19
|
+
<span class="hint">Select a task to open its form.</span>
|
|
20
|
+
</header>
|
|
21
|
+
<div id="inbox-detail-body" class="ax-inbox__detail-body"></div>
|
|
22
|
+
</section>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div id="inbox-toast" class="ax-inbox__toast" hidden></div>`;return a({title:"AgentX \xB7 Inbox",activeTab:"workflows",subtitle:"Inbox",peers:e.peers,currentPeerId:e.currentPeerId,body:o,css:n,scripts:`<script>${i}</script>`})}var n=`
|
|
26
|
+
.ax-inbox__root {
|
|
27
|
+
display: grid;
|
|
28
|
+
grid-template-columns: 340px 1fr;
|
|
29
|
+
height: calc(100vh - var(--ax-topbar-h, 48px));
|
|
30
|
+
background: var(--ax-bg);
|
|
31
|
+
}
|
|
32
|
+
.ax-inbox__list {
|
|
33
|
+
border-right: 1px solid var(--ax-border);
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
min-height: 0;
|
|
37
|
+
}
|
|
38
|
+
.ax-inbox__list > header {
|
|
39
|
+
display: flex;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
align-items: center;
|
|
42
|
+
padding: 12px 14px;
|
|
43
|
+
border-bottom: 1px solid var(--ax-border);
|
|
44
|
+
}
|
|
45
|
+
.ax-inbox__list > header h2 { margin: 0; font-size: 14px; font-weight: 600; }
|
|
46
|
+
.ax-inbox__actor {
|
|
47
|
+
padding: 10px 14px;
|
|
48
|
+
border-bottom: 1px solid var(--ax-border);
|
|
49
|
+
}
|
|
50
|
+
.ax-inbox__actor label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--ax-muted); }
|
|
51
|
+
.ax-inbox__actor input {
|
|
52
|
+
font: inherit;
|
|
53
|
+
padding: 6px 8px;
|
|
54
|
+
border: 1px solid var(--ax-border);
|
|
55
|
+
border-radius: 6px;
|
|
56
|
+
background: var(--ax-bg);
|
|
57
|
+
color: var(--ax-fg);
|
|
58
|
+
}
|
|
59
|
+
.ax-inbox__cards { list-style: none; margin: 0; padding: 6px; overflow-y: auto; flex: 1; }
|
|
60
|
+
.ax-inbox__card {
|
|
61
|
+
padding: 10px 12px;
|
|
62
|
+
border-radius: 6px;
|
|
63
|
+
margin-bottom: 4px;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
border: 1px solid transparent;
|
|
66
|
+
}
|
|
67
|
+
.ax-inbox__card:hover { background: var(--ax-surface-2, rgba(127,127,127,0.08)); }
|
|
68
|
+
.ax-inbox__card.is-active { background: var(--ax-surface-2); border-color: var(--ax-border); }
|
|
69
|
+
.ax-inbox__card-title { font-weight: 600; font-size: 13px; margin-bottom: 2px; }
|
|
70
|
+
.ax-inbox__card-meta { font-size: 11px; color: var(--ax-muted); }
|
|
71
|
+
.ax-inbox__card-due { font-size: 11px; color: #d48a00; margin-top: 4px; }
|
|
72
|
+
.ax-inbox__empty { padding: 20px; color: var(--ax-muted); text-align: center; font-size: 13px; }
|
|
73
|
+
.ax-inbox__detail { display: flex; flex-direction: column; min-height: 0; }
|
|
74
|
+
.ax-inbox__detail > header { padding: 14px 18px; border-bottom: 1px solid var(--ax-border); }
|
|
75
|
+
.ax-inbox__detail-body { overflow-y: auto; padding: 18px; flex: 1; }
|
|
76
|
+
.ax-inbox__form { max-width: 560px; display: grid; gap: 14px; }
|
|
77
|
+
.ax-inbox__field { display: flex; flex-direction: column; gap: 4px; }
|
|
78
|
+
.ax-inbox__field label { font-size: 12px; color: var(--ax-muted); font-weight: 600; }
|
|
79
|
+
.ax-inbox__field input, .ax-inbox__field textarea, .ax-inbox__field select {
|
|
80
|
+
font: inherit;
|
|
81
|
+
padding: 8px 10px;
|
|
82
|
+
border: 1px solid var(--ax-border);
|
|
83
|
+
border-radius: 6px;
|
|
84
|
+
background: var(--ax-bg);
|
|
85
|
+
color: var(--ax-fg);
|
|
86
|
+
}
|
|
87
|
+
.ax-inbox__field textarea { min-height: 100px; resize: vertical; }
|
|
88
|
+
.ax-inbox__field-hint { font-size: 11px; color: var(--ax-muted); }
|
|
89
|
+
.ax-inbox__field-error { font-size: 11px; color: #c0392b; }
|
|
90
|
+
.ax-inbox__actions { display: flex; gap: 8px; margin-top: 8px; }
|
|
91
|
+
.ax-inbox__actions button {
|
|
92
|
+
font: inherit;
|
|
93
|
+
padding: 8px 14px;
|
|
94
|
+
border: 1px solid var(--ax-border);
|
|
95
|
+
border-radius: 6px;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
background: var(--ax-surface-2);
|
|
98
|
+
color: var(--ax-fg);
|
|
99
|
+
}
|
|
100
|
+
.ax-inbox__actions button.is-primary {
|
|
101
|
+
background: #2ecc71; color: white; border-color: #27ae60;
|
|
102
|
+
}
|
|
103
|
+
.ax-inbox__actions button:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
104
|
+
.ax-inbox__icon {
|
|
105
|
+
background: none; border: 1px solid transparent; color: var(--ax-fg); cursor: pointer;
|
|
106
|
+
font-size: 14px; padding: 4px 8px; border-radius: 4px;
|
|
107
|
+
}
|
|
108
|
+
.ax-inbox__icon:hover { background: var(--ax-surface-2); }
|
|
109
|
+
.ax-inbox__toast {
|
|
110
|
+
position: fixed; bottom: 16px; right: 16px; padding: 10px 14px;
|
|
111
|
+
background: var(--ax-fg); color: var(--ax-bg); border-radius: 6px;
|
|
112
|
+
font-size: 13px; z-index: 100;
|
|
113
|
+
}
|
|
114
|
+
`,i=`
|
|
115
|
+
(function(){
|
|
116
|
+
const $ = (sel) => document.querySelector(sel);
|
|
117
|
+
const state = { tasks: [], selected: null, actor: document.querySelector('.ax-inbox__root').dataset.actor || '' };
|
|
118
|
+
const toast = (msg) => {
|
|
119
|
+
const el = $('#inbox-toast');
|
|
120
|
+
el.textContent = msg;
|
|
121
|
+
el.hidden = false;
|
|
122
|
+
setTimeout(() => { el.hidden = true; }, 2500);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
async function fetchTasks() {
|
|
126
|
+
const qs = state.actor ? ('?actor=' + encodeURIComponent(state.actor)) : '';
|
|
127
|
+
try {
|
|
128
|
+
const r = await fetch('/api/workflows/tasks' + qs, { credentials: 'same-origin' });
|
|
129
|
+
if (!r.ok) { toast('fetch failed: ' + r.status); return; }
|
|
130
|
+
const data = await r.json();
|
|
131
|
+
state.tasks = Array.isArray(data.tasks) ? data.tasks : [];
|
|
132
|
+
renderList();
|
|
133
|
+
if (state.selected && !state.tasks.find(t => t.id === state.selected)) {
|
|
134
|
+
state.selected = null;
|
|
135
|
+
renderDetail();
|
|
136
|
+
}
|
|
137
|
+
} catch (e) { toast('fetch error: ' + e.message); }
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function renderList() {
|
|
141
|
+
const ul = $('#inbox-tasks');
|
|
142
|
+
const empty = $('#inbox-empty');
|
|
143
|
+
ul.innerHTML = '';
|
|
144
|
+
if (!state.tasks.length) { empty.hidden = false; return; }
|
|
145
|
+
empty.hidden = true;
|
|
146
|
+
for (const t of state.tasks) {
|
|
147
|
+
const li = document.createElement('li');
|
|
148
|
+
li.className = 'ax-inbox__card' + (t.id === state.selected ? ' is-active' : '');
|
|
149
|
+
li.innerHTML =
|
|
150
|
+
'<div class="ax-inbox__card-title">' + escHtml(t.title) + '</div>' +
|
|
151
|
+
'<div class="ax-inbox__card-meta">' + escHtml(t.assignee) + ' \xB7 ' + escHtml(t.workflowId) + '</div>' +
|
|
152
|
+
(t.dueAt ? ('<div class="ax-inbox__card-due">due ' + new Date(t.dueAt).toLocaleString() + '</div>') : '');
|
|
153
|
+
li.addEventListener('click', () => { state.selected = t.id; renderList(); renderDetail(); });
|
|
154
|
+
ul.appendChild(li);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function renderDetail() {
|
|
159
|
+
const head = $('#inbox-detail-head');
|
|
160
|
+
const body = $('#inbox-detail-body');
|
|
161
|
+
const t = state.tasks.find(x => x.id === state.selected);
|
|
162
|
+
if (!t) {
|
|
163
|
+
head.innerHTML = '<span class="hint">Select a task to open its form.</span>';
|
|
164
|
+
body.innerHTML = '';
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
head.innerHTML = '<h2 style="margin:0;font-size:15px">' + escHtml(t.title) + '</h2>' +
|
|
168
|
+
(t.description ? '<p class="hint" style="margin:6px 0 0">' + escHtml(t.description) + '</p>' : '');
|
|
169
|
+
const form = document.createElement('form');
|
|
170
|
+
form.className = 'ax-inbox__form';
|
|
171
|
+
form.addEventListener('submit', (e) => { e.preventDefault(); submit(t, 'primary'); });
|
|
172
|
+
for (const field of (t.form.fields || [])) {
|
|
173
|
+
form.appendChild(renderField(field));
|
|
174
|
+
}
|
|
175
|
+
const actions = document.createElement('div');
|
|
176
|
+
actions.className = 'ax-inbox__actions';
|
|
177
|
+
const primary = document.createElement('button');
|
|
178
|
+
primary.type = 'submit';
|
|
179
|
+
primary.className = 'is-primary';
|
|
180
|
+
primary.textContent = t.form.submitLabel || 'Submit';
|
|
181
|
+
actions.appendChild(primary);
|
|
182
|
+
if (t.form.secondaryAction) {
|
|
183
|
+
const secondary = document.createElement('button');
|
|
184
|
+
secondary.type = 'button';
|
|
185
|
+
secondary.textContent = t.form.secondaryAction.label;
|
|
186
|
+
secondary.addEventListener('click', () => submit(t, 'secondary'));
|
|
187
|
+
actions.appendChild(secondary);
|
|
188
|
+
}
|
|
189
|
+
form.appendChild(actions);
|
|
190
|
+
body.innerHTML = '';
|
|
191
|
+
body.appendChild(form);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function renderField(field) {
|
|
195
|
+
const wrap = document.createElement('div');
|
|
196
|
+
wrap.className = 'ax-inbox__field';
|
|
197
|
+
const label = document.createElement('label');
|
|
198
|
+
label.textContent = field.label + (field.required ? ' *' : '');
|
|
199
|
+
wrap.appendChild(label);
|
|
200
|
+
let input;
|
|
201
|
+
switch (field.type) {
|
|
202
|
+
case 'long-text':
|
|
203
|
+
input = document.createElement('textarea');
|
|
204
|
+
break;
|
|
205
|
+
case 'number':
|
|
206
|
+
input = document.createElement('input'); input.type = 'number';
|
|
207
|
+
break;
|
|
208
|
+
case 'boolean':
|
|
209
|
+
input = document.createElement('select');
|
|
210
|
+
for (const v of ['', 'yes', 'no']) {
|
|
211
|
+
const o = document.createElement('option'); o.value = v; o.textContent = v || '\u2014';
|
|
212
|
+
input.appendChild(o);
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
case 'date':
|
|
216
|
+
input = document.createElement('input'); input.type = 'date';
|
|
217
|
+
break;
|
|
218
|
+
case 'select':
|
|
219
|
+
input = document.createElement('select');
|
|
220
|
+
if (!field.required) { const o = document.createElement('option'); o.value = ''; o.textContent = '\u2014'; input.appendChild(o); }
|
|
221
|
+
for (const opt of (field.options || [])) {
|
|
222
|
+
const o = document.createElement('option'); o.value = opt; o.textContent = opt;
|
|
223
|
+
input.appendChild(o);
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
case 'multi-select':
|
|
227
|
+
input = document.createElement('select'); input.multiple = true; input.size = Math.min(6, (field.options||[]).length || 3);
|
|
228
|
+
for (const opt of (field.options || [])) {
|
|
229
|
+
const o = document.createElement('option'); o.value = opt; o.textContent = opt;
|
|
230
|
+
input.appendChild(o);
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
case 'file':
|
|
234
|
+
input = document.createElement('input'); input.type = 'text'; input.placeholder = 'URL or path';
|
|
235
|
+
break;
|
|
236
|
+
default:
|
|
237
|
+
input = document.createElement('input'); input.type = 'text';
|
|
238
|
+
}
|
|
239
|
+
input.name = field.key;
|
|
240
|
+
if (field.defaultValue !== undefined && field.type !== 'multi-select') input.value = String(field.defaultValue);
|
|
241
|
+
wrap.appendChild(input);
|
|
242
|
+
if (field.hint) {
|
|
243
|
+
const hint = document.createElement('div');
|
|
244
|
+
hint.className = 'ax-inbox__field-hint';
|
|
245
|
+
hint.textContent = field.hint;
|
|
246
|
+
wrap.appendChild(hint);
|
|
247
|
+
}
|
|
248
|
+
const err = document.createElement('div');
|
|
249
|
+
err.className = 'ax-inbox__field-error';
|
|
250
|
+
err.dataset.for = field.key;
|
|
251
|
+
wrap.appendChild(err);
|
|
252
|
+
return wrap;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function submit(task, action) {
|
|
256
|
+
const form = $('.ax-inbox__form');
|
|
257
|
+
if (!form) return;
|
|
258
|
+
const values = {};
|
|
259
|
+
for (const field of (task.form.fields || [])) {
|
|
260
|
+
const el = form.querySelector('[name="' + field.key + '"]');
|
|
261
|
+
if (!el) continue;
|
|
262
|
+
if (field.type === 'multi-select') {
|
|
263
|
+
values[field.key] = Array.from(el.selectedOptions).map(o => o.value);
|
|
264
|
+
} else if (field.type === 'boolean') {
|
|
265
|
+
values[field.key] = el.value;
|
|
266
|
+
} else {
|
|
267
|
+
values[field.key] = el.value;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
form.querySelectorAll('.ax-inbox__field-error').forEach(e => { e.textContent = ''; });
|
|
271
|
+
try {
|
|
272
|
+
const r = await fetch('/api/workflows/tasks/' + encodeURIComponent(task.id) + '/submit', {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
credentials: 'same-origin',
|
|
275
|
+
headers: { 'Content-Type': 'application/json' },
|
|
276
|
+
body: JSON.stringify({ submittedBy: state.actor || 'anonymous', submission: { action, values } }),
|
|
277
|
+
});
|
|
278
|
+
const data = await r.json().catch(() => ({}));
|
|
279
|
+
if (!r.ok) {
|
|
280
|
+
if (data.fieldErrors && Array.isArray(data.fieldErrors)) {
|
|
281
|
+
for (const fe of data.fieldErrors) {
|
|
282
|
+
const node = form.querySelector('[data-for="' + fe.field + '"]');
|
|
283
|
+
if (node) node.textContent = fe.message;
|
|
284
|
+
}
|
|
285
|
+
toast('form has errors');
|
|
286
|
+
} else {
|
|
287
|
+
toast(data.error || 'submit failed');
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
toast('submitted');
|
|
292
|
+
state.selected = null;
|
|
293
|
+
fetchTasks();
|
|
294
|
+
} catch (e) { toast('submit error: ' + e.message); }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function escHtml(s) {
|
|
298
|
+
return String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c]);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
$('#inbox-actor').addEventListener('change', (e) => {
|
|
302
|
+
state.actor = e.target.value.trim();
|
|
303
|
+
state.selected = null;
|
|
304
|
+
const url = new URL(window.location.href);
|
|
305
|
+
if (state.actor) url.searchParams.set('actor', state.actor); else url.searchParams.delete('actor');
|
|
306
|
+
history.replaceState({}, '', url.toString());
|
|
307
|
+
fetchTasks();
|
|
308
|
+
});
|
|
309
|
+
$('#inbox-refresh').addEventListener('click', fetchTasks);
|
|
310
|
+
|
|
311
|
+
fetchTasks();
|
|
312
|
+
setInterval(fetchTasks, 10000);
|
|
313
|
+
})();
|
|
314
|
+
`;export{s as renderInboxPage};
|
|
315
|
+
//# sourceMappingURL=inbox-L5ZZ623Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/daemon/ui/pages/inbox.ts"],"sourcesContent":["import { renderShell, esc, type TopbarPeer } from \"..\"\n\n// --- Inbox page ---\n//\n// Per-actor (or global) list of open user-tasks with an inline form\n// renderer. Reads /api/workflows/tasks; submits via\n// POST /api/workflows/tasks/:id/submit.\n//\n// Scope is intentionally tight for Phase 1:\n// - text / long-text / number / boolean / select / multi-select / date\n// - primary + optional secondary action buttons\n// - required-field validation is server-side; the UI just relays errors\n//\n// No channel-adapter coupling here — the form UI is the same whether the\n// renderer ran on Telegram or not.\n\nexport interface InboxPageOpts {\n peers?: TopbarPeer[]\n currentPeerId?: string\n /** Optional actor id to pre-filter. When unset, the page shows a prompt\n * asking the user to pick their actor id. */\n actor?: string\n}\n\nexport function renderInboxPage(opts: InboxPageOpts = {}): string {\n const body = `<div class=\"ax-inbox__root\" data-actor=\"${esc(opts.actor ?? \"\")}\">\n <aside class=\"ax-inbox__list\">\n <header>\n <h2>Inbox</h2>\n <button id=\"inbox-refresh\" class=\"ax-inbox__icon\" title=\"Refresh (r)\">↻</button>\n </header>\n <div class=\"ax-inbox__actor\">\n <label>Actor <input id=\"inbox-actor\" type=\"text\" placeholder=\"actor:<id>\" value=\"${esc(opts.actor ?? \"\")}\" autocomplete=\"off\" /></label>\n </div>\n <ul id=\"inbox-tasks\" class=\"ax-inbox__cards\" aria-live=\"polite\"></ul>\n <div id=\"inbox-empty\" class=\"ax-inbox__empty\" hidden>\n <p>No open tasks.</p>\n <p class=\"hint\">Set the actor filter to see tasks assigned to you, or leave blank for all tasks in the system.</p>\n </div>\n </aside>\n\n <section class=\"ax-inbox__detail\">\n <header id=\"inbox-detail-head\">\n <span class=\"hint\">Select a task to open its form.</span>\n </header>\n <div id=\"inbox-detail-body\" class=\"ax-inbox__detail-body\"></div>\n </section>\n</div>\n\n<div id=\"inbox-toast\" class=\"ax-inbox__toast\" hidden></div>`\n\n return renderShell({\n title: \"AgentX · Inbox\",\n activeTab: \"workflows\",\n subtitle: \"Inbox\",\n peers: opts.peers,\n currentPeerId: opts.currentPeerId,\n body,\n css: INBOX_PAGE_CSS,\n scripts: `<script>${INBOX_PAGE_SCRIPT}</script>`,\n })\n}\n\nconst INBOX_PAGE_CSS = `\n.ax-inbox__root {\n display: grid;\n grid-template-columns: 340px 1fr;\n height: calc(100vh - var(--ax-topbar-h, 48px));\n background: var(--ax-bg);\n}\n.ax-inbox__list {\n border-right: 1px solid var(--ax-border);\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n.ax-inbox__list > header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 14px;\n border-bottom: 1px solid var(--ax-border);\n}\n.ax-inbox__list > header h2 { margin: 0; font-size: 14px; font-weight: 600; }\n.ax-inbox__actor {\n padding: 10px 14px;\n border-bottom: 1px solid var(--ax-border);\n}\n.ax-inbox__actor label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--ax-muted); }\n.ax-inbox__actor input {\n font: inherit;\n padding: 6px 8px;\n border: 1px solid var(--ax-border);\n border-radius: 6px;\n background: var(--ax-bg);\n color: var(--ax-fg);\n}\n.ax-inbox__cards { list-style: none; margin: 0; padding: 6px; overflow-y: auto; flex: 1; }\n.ax-inbox__card {\n padding: 10px 12px;\n border-radius: 6px;\n margin-bottom: 4px;\n cursor: pointer;\n border: 1px solid transparent;\n}\n.ax-inbox__card:hover { background: var(--ax-surface-2, rgba(127,127,127,0.08)); }\n.ax-inbox__card.is-active { background: var(--ax-surface-2); border-color: var(--ax-border); }\n.ax-inbox__card-title { font-weight: 600; font-size: 13px; margin-bottom: 2px; }\n.ax-inbox__card-meta { font-size: 11px; color: var(--ax-muted); }\n.ax-inbox__card-due { font-size: 11px; color: #d48a00; margin-top: 4px; }\n.ax-inbox__empty { padding: 20px; color: var(--ax-muted); text-align: center; font-size: 13px; }\n.ax-inbox__detail { display: flex; flex-direction: column; min-height: 0; }\n.ax-inbox__detail > header { padding: 14px 18px; border-bottom: 1px solid var(--ax-border); }\n.ax-inbox__detail-body { overflow-y: auto; padding: 18px; flex: 1; }\n.ax-inbox__form { max-width: 560px; display: grid; gap: 14px; }\n.ax-inbox__field { display: flex; flex-direction: column; gap: 4px; }\n.ax-inbox__field label { font-size: 12px; color: var(--ax-muted); font-weight: 600; }\n.ax-inbox__field input, .ax-inbox__field textarea, .ax-inbox__field select {\n font: inherit;\n padding: 8px 10px;\n border: 1px solid var(--ax-border);\n border-radius: 6px;\n background: var(--ax-bg);\n color: var(--ax-fg);\n}\n.ax-inbox__field textarea { min-height: 100px; resize: vertical; }\n.ax-inbox__field-hint { font-size: 11px; color: var(--ax-muted); }\n.ax-inbox__field-error { font-size: 11px; color: #c0392b; }\n.ax-inbox__actions { display: flex; gap: 8px; margin-top: 8px; }\n.ax-inbox__actions button {\n font: inherit;\n padding: 8px 14px;\n border: 1px solid var(--ax-border);\n border-radius: 6px;\n cursor: pointer;\n background: var(--ax-surface-2);\n color: var(--ax-fg);\n}\n.ax-inbox__actions button.is-primary {\n background: #2ecc71; color: white; border-color: #27ae60;\n}\n.ax-inbox__actions button:disabled { opacity: 0.5; cursor: not-allowed; }\n.ax-inbox__icon {\n background: none; border: 1px solid transparent; color: var(--ax-fg); cursor: pointer;\n font-size: 14px; padding: 4px 8px; border-radius: 4px;\n}\n.ax-inbox__icon:hover { background: var(--ax-surface-2); }\n.ax-inbox__toast {\n position: fixed; bottom: 16px; right: 16px; padding: 10px 14px;\n background: var(--ax-fg); color: var(--ax-bg); border-radius: 6px;\n font-size: 13px; z-index: 100;\n}\n`\n\n// Deliberately vanilla JS — no framework dep. Fetches task list, renders\n// per-field inputs, POSTs submission.\nconst INBOX_PAGE_SCRIPT = `\n(function(){\n const $ = (sel) => document.querySelector(sel);\n const state = { tasks: [], selected: null, actor: document.querySelector('.ax-inbox__root').dataset.actor || '' };\n const toast = (msg) => {\n const el = $('#inbox-toast');\n el.textContent = msg;\n el.hidden = false;\n setTimeout(() => { el.hidden = true; }, 2500);\n };\n\n async function fetchTasks() {\n const qs = state.actor ? ('?actor=' + encodeURIComponent(state.actor)) : '';\n try {\n const r = await fetch('/api/workflows/tasks' + qs, { credentials: 'same-origin' });\n if (!r.ok) { toast('fetch failed: ' + r.status); return; }\n const data = await r.json();\n state.tasks = Array.isArray(data.tasks) ? data.tasks : [];\n renderList();\n if (state.selected && !state.tasks.find(t => t.id === state.selected)) {\n state.selected = null;\n renderDetail();\n }\n } catch (e) { toast('fetch error: ' + e.message); }\n }\n\n function renderList() {\n const ul = $('#inbox-tasks');\n const empty = $('#inbox-empty');\n ul.innerHTML = '';\n if (!state.tasks.length) { empty.hidden = false; return; }\n empty.hidden = true;\n for (const t of state.tasks) {\n const li = document.createElement('li');\n li.className = 'ax-inbox__card' + (t.id === state.selected ? ' is-active' : '');\n li.innerHTML =\n '<div class=\"ax-inbox__card-title\">' + escHtml(t.title) + '</div>' +\n '<div class=\"ax-inbox__card-meta\">' + escHtml(t.assignee) + ' · ' + escHtml(t.workflowId) + '</div>' +\n (t.dueAt ? ('<div class=\"ax-inbox__card-due\">due ' + new Date(t.dueAt).toLocaleString() + '</div>') : '');\n li.addEventListener('click', () => { state.selected = t.id; renderList(); renderDetail(); });\n ul.appendChild(li);\n }\n }\n\n function renderDetail() {\n const head = $('#inbox-detail-head');\n const body = $('#inbox-detail-body');\n const t = state.tasks.find(x => x.id === state.selected);\n if (!t) {\n head.innerHTML = '<span class=\"hint\">Select a task to open its form.</span>';\n body.innerHTML = '';\n return;\n }\n head.innerHTML = '<h2 style=\"margin:0;font-size:15px\">' + escHtml(t.title) + '</h2>' +\n (t.description ? '<p class=\"hint\" style=\"margin:6px 0 0\">' + escHtml(t.description) + '</p>' : '');\n const form = document.createElement('form');\n form.className = 'ax-inbox__form';\n form.addEventListener('submit', (e) => { e.preventDefault(); submit(t, 'primary'); });\n for (const field of (t.form.fields || [])) {\n form.appendChild(renderField(field));\n }\n const actions = document.createElement('div');\n actions.className = 'ax-inbox__actions';\n const primary = document.createElement('button');\n primary.type = 'submit';\n primary.className = 'is-primary';\n primary.textContent = t.form.submitLabel || 'Submit';\n actions.appendChild(primary);\n if (t.form.secondaryAction) {\n const secondary = document.createElement('button');\n secondary.type = 'button';\n secondary.textContent = t.form.secondaryAction.label;\n secondary.addEventListener('click', () => submit(t, 'secondary'));\n actions.appendChild(secondary);\n }\n form.appendChild(actions);\n body.innerHTML = '';\n body.appendChild(form);\n }\n\n function renderField(field) {\n const wrap = document.createElement('div');\n wrap.className = 'ax-inbox__field';\n const label = document.createElement('label');\n label.textContent = field.label + (field.required ? ' *' : '');\n wrap.appendChild(label);\n let input;\n switch (field.type) {\n case 'long-text':\n input = document.createElement('textarea');\n break;\n case 'number':\n input = document.createElement('input'); input.type = 'number';\n break;\n case 'boolean':\n input = document.createElement('select');\n for (const v of ['', 'yes', 'no']) {\n const o = document.createElement('option'); o.value = v; o.textContent = v || '—';\n input.appendChild(o);\n }\n break;\n case 'date':\n input = document.createElement('input'); input.type = 'date';\n break;\n case 'select':\n input = document.createElement('select');\n if (!field.required) { const o = document.createElement('option'); o.value = ''; o.textContent = '—'; input.appendChild(o); }\n for (const opt of (field.options || [])) {\n const o = document.createElement('option'); o.value = opt; o.textContent = opt;\n input.appendChild(o);\n }\n break;\n case 'multi-select':\n input = document.createElement('select'); input.multiple = true; input.size = Math.min(6, (field.options||[]).length || 3);\n for (const opt of (field.options || [])) {\n const o = document.createElement('option'); o.value = opt; o.textContent = opt;\n input.appendChild(o);\n }\n break;\n case 'file':\n input = document.createElement('input'); input.type = 'text'; input.placeholder = 'URL or path';\n break;\n default:\n input = document.createElement('input'); input.type = 'text';\n }\n input.name = field.key;\n if (field.defaultValue !== undefined && field.type !== 'multi-select') input.value = String(field.defaultValue);\n wrap.appendChild(input);\n if (field.hint) {\n const hint = document.createElement('div');\n hint.className = 'ax-inbox__field-hint';\n hint.textContent = field.hint;\n wrap.appendChild(hint);\n }\n const err = document.createElement('div');\n err.className = 'ax-inbox__field-error';\n err.dataset.for = field.key;\n wrap.appendChild(err);\n return wrap;\n }\n\n async function submit(task, action) {\n const form = $('.ax-inbox__form');\n if (!form) return;\n const values = {};\n for (const field of (task.form.fields || [])) {\n const el = form.querySelector('[name=\"' + field.key + '\"]');\n if (!el) continue;\n if (field.type === 'multi-select') {\n values[field.key] = Array.from(el.selectedOptions).map(o => o.value);\n } else if (field.type === 'boolean') {\n values[field.key] = el.value;\n } else {\n values[field.key] = el.value;\n }\n }\n form.querySelectorAll('.ax-inbox__field-error').forEach(e => { e.textContent = ''; });\n try {\n const r = await fetch('/api/workflows/tasks/' + encodeURIComponent(task.id) + '/submit', {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ submittedBy: state.actor || 'anonymous', submission: { action, values } }),\n });\n const data = await r.json().catch(() => ({}));\n if (!r.ok) {\n if (data.fieldErrors && Array.isArray(data.fieldErrors)) {\n for (const fe of data.fieldErrors) {\n const node = form.querySelector('[data-for=\"' + fe.field + '\"]');\n if (node) node.textContent = fe.message;\n }\n toast('form has errors');\n } else {\n toast(data.error || 'submit failed');\n }\n return;\n }\n toast('submitted');\n state.selected = null;\n fetchTasks();\n } catch (e) { toast('submit error: ' + e.message); }\n }\n\n function escHtml(s) {\n return String(s).replace(/[&<>\"']/g, c => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''})[c]);\n }\n\n $('#inbox-actor').addEventListener('change', (e) => {\n state.actor = e.target.value.trim();\n state.selected = null;\n const url = new URL(window.location.href);\n if (state.actor) url.searchParams.set('actor', state.actor); else url.searchParams.delete('actor');\n history.replaceState({}, '', url.toString());\n fetchTasks();\n });\n $('#inbox-refresh').addEventListener('click', fetchTasks);\n\n fetchTasks();\n setInterval(fetchTasks, 10000);\n})();\n`\n"],"mappings":"sEAwBO,SAASA,EAAgBC,EAAsB,CAAC,EAAW,CAChE,IAAMC,EAAO,2CAA2CC,EAAIF,EAAK,OAAS,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yFAOWE,EAAIF,EAAK,OAAS,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6DAmB3G,OAAOG,EAAY,CACjB,MAAO,oBACP,UAAW,YACX,SAAU,QACV,MAAOH,EAAK,MACZ,cAAeA,EAAK,cACpB,KAAAC,EACA,IAAKG,EACL,QAAS,WAAWC,YACtB,CAAC,CACH,CAEA,IAAMD,EAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6FjBC,EAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":["renderInboxPage","opts","body","esc","renderShell","INBOX_PAGE_CSS","INBOX_PAGE_SCRIPT"]}
|