atris 3.15.53 → 3.15.55
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/commands/computer.js +21 -1
- package/commands/integrations.js +83 -22
- package/commands/xp.js +61 -5
- package/package.json +1 -1
package/commands/computer.js
CHANGED
|
@@ -1126,15 +1126,35 @@ async function resolveComputerCommandContext(token, options = {}) {
|
|
|
1126
1126
|
? await resolveBusinessContextBySlug(token, options.businessSlug, { preferCache: true })
|
|
1127
1127
|
: await resolveBusinessContext(token);
|
|
1128
1128
|
if (!ctx?.businessId) return null;
|
|
1129
|
+
const workspaceId = options.workspaceId
|
|
1130
|
+
? await resolveWorkspaceSelector(token, ctx, options.workspaceId)
|
|
1131
|
+
: ctx.workspaceId;
|
|
1129
1132
|
return {
|
|
1130
1133
|
...ctx,
|
|
1131
|
-
workspaceId
|
|
1134
|
+
workspaceId,
|
|
1132
1135
|
};
|
|
1133
1136
|
}
|
|
1134
1137
|
|
|
1135
1138
|
return resolveBusinessContext(token);
|
|
1136
1139
|
}
|
|
1137
1140
|
|
|
1141
|
+
function looksLikeWorkspaceId(input) {
|
|
1142
|
+
const value = String(input || '').trim();
|
|
1143
|
+
if (!value) return false;
|
|
1144
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)
|
|
1145
|
+
|| /^ws-[a-z0-9_-]+$/i.test(value);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
async function resolveWorkspaceSelector(token, ctx, input) {
|
|
1149
|
+
const selector = String(input || '').trim();
|
|
1150
|
+
if (!selector) return ctx.workspaceId;
|
|
1151
|
+
if (selector === ctx.workspaceId || looksLikeWorkspaceId(selector)) return selector;
|
|
1152
|
+
|
|
1153
|
+
const workspaces = await listBusinessWorkspaces(token, ctx);
|
|
1154
|
+
const workspace = resolveWorkspaceFromList(workspaces, selector);
|
|
1155
|
+
return workspace?.id || selector;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1138
1158
|
async function resolveBusinessOwnerForCreate(token, businessSlug = null) {
|
|
1139
1159
|
const wantedSlug = businessSlug ? String(businessSlug).trim() : null;
|
|
1140
1160
|
if (wantedSlug) {
|
package/commands/integrations.js
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* atris gmail inbox - List recent emails
|
|
6
6
|
* atris gmail read <id> - Read specific email
|
|
7
7
|
* atris calendar today - Show today's events
|
|
8
|
+
* atris calendar yesterday - Show yesterday's events
|
|
8
9
|
* atris calendar week - Show this week's events
|
|
10
|
+
* atris calendar date YYYY-MM-DD - Show events on a date
|
|
9
11
|
* atris twitter post - Post a tweet (interactive)
|
|
10
12
|
* atris slack channels - List Slack channels
|
|
11
13
|
*/
|
|
@@ -137,12 +139,63 @@ async function gmailCommand(subcommand, ...args) {
|
|
|
137
139
|
// CALENDAR
|
|
138
140
|
// ============================================================================
|
|
139
141
|
|
|
140
|
-
|
|
142
|
+
function localDayBounds(offsetDays = 0) {
|
|
143
|
+
const start = new Date();
|
|
144
|
+
start.setHours(0, 0, 0, 0);
|
|
145
|
+
start.setDate(start.getDate() + offsetDays);
|
|
146
|
+
const end = new Date(start);
|
|
147
|
+
end.setDate(end.getDate() + 1);
|
|
148
|
+
return { start, end };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function localDateBounds(dateText) {
|
|
152
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(String(dateText || ''))) {
|
|
153
|
+
console.error('Usage: atris calendar date YYYY-MM-DD');
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
const start = new Date(`${dateText}T00:00:00`);
|
|
157
|
+
if (Number.isNaN(start.getTime())) {
|
|
158
|
+
console.error('Invalid date. Use YYYY-MM-DD.');
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
const end = new Date(start);
|
|
162
|
+
end.setDate(end.getDate() + 1);
|
|
163
|
+
return { start, end };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function formatCalendarEvents(label, events) {
|
|
167
|
+
if (events.length === 0) {
|
|
168
|
+
console.log(`No events ${label}. 🎉`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
console.log('─'.repeat(50));
|
|
173
|
+
|
|
174
|
+
for (const event of events) {
|
|
175
|
+
const start = event.start?.dateTime || event.start?.date || '';
|
|
176
|
+
const time = start ? new Date(start).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) : 'All day';
|
|
177
|
+
const title = event.summary || '(no title)';
|
|
178
|
+
|
|
179
|
+
console.log(`${time} ${title}`);
|
|
180
|
+
if (event.location) {
|
|
181
|
+
console.log(` 📍 ${event.location}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log('─'.repeat(50));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function calendarRange(label, { timeMin, timeMax, days } = {}) {
|
|
141
189
|
const { token, email } = await getAuth();
|
|
142
190
|
|
|
143
|
-
console.log(
|
|
191
|
+
console.log(`📅 ${label}:\n`);
|
|
144
192
|
|
|
145
|
-
const
|
|
193
|
+
const params = new URLSearchParams();
|
|
194
|
+
if (timeMin) params.set('time_min', timeMin);
|
|
195
|
+
if (timeMax) params.set('time_max', timeMax);
|
|
196
|
+
if (days) params.set('days', String(days));
|
|
197
|
+
const suffix = params.toString() ? `?${params.toString()}` : '';
|
|
198
|
+
const result = await apiRequestJson(`/integrations/google-calendar/events${suffix}`, {
|
|
146
199
|
method: 'GET',
|
|
147
200
|
token,
|
|
148
201
|
});
|
|
@@ -159,26 +212,25 @@ async function calendarToday() {
|
|
|
159
212
|
}
|
|
160
213
|
|
|
161
214
|
const events = result.data?.events || result.data || [];
|
|
215
|
+
formatCalendarEvents(label.toLowerCase(), events);
|
|
216
|
+
}
|
|
162
217
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
console.log('─'.repeat(50));
|
|
218
|
+
async function calendarToday() {
|
|
219
|
+
await calendarRange("Today's events", { days: 1 });
|
|
220
|
+
}
|
|
169
221
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
222
|
+
async function calendarYesterday() {
|
|
223
|
+
const { start, end } = localDayBounds(-1);
|
|
224
|
+
await calendarRange("Yesterday's events", { timeMin: start.toISOString(), timeMax: end.toISOString() });
|
|
225
|
+
}
|
|
174
226
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
}
|
|
227
|
+
async function calendarWeek() {
|
|
228
|
+
await calendarRange("This week's events", { days: 7 });
|
|
229
|
+
}
|
|
180
230
|
|
|
181
|
-
|
|
231
|
+
async function calendarDate(dateText) {
|
|
232
|
+
const { start, end } = localDateBounds(dateText);
|
|
233
|
+
await calendarRange(`Events on ${dateText}`, { timeMin: start.toISOString(), timeMax: end.toISOString() });
|
|
182
234
|
}
|
|
183
235
|
|
|
184
236
|
async function calendarCommand(subcommand, ...args) {
|
|
@@ -186,13 +238,22 @@ async function calendarCommand(subcommand, ...args) {
|
|
|
186
238
|
case 'today':
|
|
187
239
|
await calendarToday();
|
|
188
240
|
break;
|
|
241
|
+
case 'yesterday':
|
|
242
|
+
case 'yday':
|
|
243
|
+
await calendarYesterday();
|
|
244
|
+
break;
|
|
189
245
|
case 'week':
|
|
190
|
-
|
|
246
|
+
await calendarWeek();
|
|
247
|
+
break;
|
|
248
|
+
case 'date':
|
|
249
|
+
await calendarDate(args[0]);
|
|
191
250
|
break;
|
|
192
251
|
default:
|
|
193
252
|
console.log('Calendar commands:');
|
|
194
|
-
console.log(' atris calendar today
|
|
195
|
-
console.log(' atris calendar
|
|
253
|
+
console.log(' atris calendar today - Show today\'s events');
|
|
254
|
+
console.log(' atris calendar yesterday - Show yesterday\'s events');
|
|
255
|
+
console.log(' atris calendar week - Show this week\'s events');
|
|
256
|
+
console.log(' atris calendar date YYYY-MM-DD - Show events on a date');
|
|
196
257
|
}
|
|
197
258
|
}
|
|
198
259
|
|
package/commands/xp.js
CHANGED
|
@@ -1727,10 +1727,34 @@ function loadLocalPayload(args) {
|
|
|
1727
1727
|
return normalizeLocalScore(JSON.parse(result.stdout), workspace);
|
|
1728
1728
|
}
|
|
1729
1729
|
|
|
1730
|
-
function
|
|
1730
|
+
function earnedAgentXp(value) {
|
|
1731
|
+
return Math.max(0, asNumber(value));
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
function currentFormScore(value) {
|
|
1731
1735
|
return Math.max(0, Math.min(99, asNumber(value)));
|
|
1732
1736
|
}
|
|
1733
1737
|
|
|
1738
|
+
function agentXpLevelProgress(totalXp) {
|
|
1739
|
+
const levelXp = Math.max(0, asNumber(totalXp));
|
|
1740
|
+
const level = levelFromXp(levelXp);
|
|
1741
|
+
const currentLevelFloor = (level - 1) * LEVEL_XP;
|
|
1742
|
+
const nextLevelXp = level * LEVEL_XP;
|
|
1743
|
+
const xpIntoLevel = levelXp - currentLevelFloor;
|
|
1744
|
+
return {
|
|
1745
|
+
schema: 'atris.agentxp_level_progress.v1',
|
|
1746
|
+
level,
|
|
1747
|
+
stage: `Level ${level}`,
|
|
1748
|
+
level_xp: levelXp,
|
|
1749
|
+
current_level_floor: currentLevelFloor,
|
|
1750
|
+
next_level_xp: nextLevelXp,
|
|
1751
|
+
xp_into_level: xpIntoLevel,
|
|
1752
|
+
xp_to_next: Math.max(0, nextLevelXp - levelXp),
|
|
1753
|
+
progress_pct: Math.max(0, Math.min(99, Math.round((xpIntoLevel / LEVEL_XP) * 100))),
|
|
1754
|
+
uncapped: true,
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1734
1758
|
function verifiedProjection(projection) {
|
|
1735
1759
|
return projection?.integrity_status === 'verified'
|
|
1736
1760
|
&& projection?.integrity?.status === 'verified';
|
|
@@ -1797,6 +1821,19 @@ function syncAttribution(workspaces) {
|
|
|
1797
1821
|
};
|
|
1798
1822
|
}
|
|
1799
1823
|
|
|
1824
|
+
function syncScopeFields(attribution = {}) {
|
|
1825
|
+
const attributionScope = slugify(attribution.attribution_scope);
|
|
1826
|
+
const orgId = String(attribution.business_id || attribution.business_slug || '').trim() || null;
|
|
1827
|
+
const businessBound = Boolean(orgId) || attributionScope === 'business-bound' || attributionScope === 'multi-business';
|
|
1828
|
+
return {
|
|
1829
|
+
scope: businessBound ? 'org' : 'global',
|
|
1830
|
+
org_id: orgId,
|
|
1831
|
+
computer_id: String(attribution.workspace_id || attribution.computer || 'local').trim() || 'local',
|
|
1832
|
+
visibility: businessBound ? 'internal' : 'public',
|
|
1833
|
+
public_agentxp: !businessBound,
|
|
1834
|
+
};
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1800
1837
|
function credentialHandle(credentials) {
|
|
1801
1838
|
return slugify(
|
|
1802
1839
|
credentials?.username
|
|
@@ -1856,19 +1893,23 @@ function buildAgentXpSyncPacket(args = []) {
|
|
|
1856
1893
|
const player = syncPlayer(args, projection);
|
|
1857
1894
|
const workspaces = projectionWorkspaceSummaries(projection);
|
|
1858
1895
|
const attribution = syncAttribution(workspaces);
|
|
1896
|
+
const scopeFields = syncScopeFields(attribution);
|
|
1859
1897
|
const totalXp = asNumber(projection.total_agent_xp ?? projection.agent_xp ?? projection.total_xp ?? projection.career_xp);
|
|
1860
1898
|
const receiptsCount = asNumber(projection.receipts_count);
|
|
1861
1899
|
const eligible = verifiedProjection(projection) && receiptsCount > 0 && totalXp > 0;
|
|
1862
|
-
const publicXp =
|
|
1900
|
+
const publicXp = earnedAgentXp(totalXp);
|
|
1901
|
+
const currentForm = currentFormScore(totalXp);
|
|
1902
|
+
const levelProgress = agentXpLevelProgress(publicXp);
|
|
1863
1903
|
const workspaceRootHash = sha256(workspaces.map(item => item.workspace_root_hash || item.name).sort().join(':'));
|
|
1864
1904
|
const entry = {
|
|
1865
1905
|
user_id: player,
|
|
1866
1906
|
username: player,
|
|
1867
1907
|
agent_xp: publicXp,
|
|
1868
1908
|
career_xp: publicXp,
|
|
1869
|
-
current_form:
|
|
1870
|
-
ovr:
|
|
1871
|
-
level:
|
|
1909
|
+
current_form: currentForm,
|
|
1910
|
+
ovr: currentForm,
|
|
1911
|
+
level: levelProgress.level,
|
|
1912
|
+
level_progress: levelProgress,
|
|
1872
1913
|
verified_receipts: receiptsCount,
|
|
1873
1914
|
reviewed_tasks: receiptsCount,
|
|
1874
1915
|
recent_verified_receipts: receiptsCount,
|
|
@@ -1883,12 +1924,17 @@ function buildAgentXpSyncPacket(args = []) {
|
|
|
1883
1924
|
schema: 'atris.agentxp_sync_packet.v1',
|
|
1884
1925
|
generated_at: new Date().toISOString(),
|
|
1885
1926
|
workspace_root_hash: workspaceRootHash,
|
|
1927
|
+
scope: scopeFields.scope,
|
|
1928
|
+
org_id: scopeFields.org_id,
|
|
1886
1929
|
attribution_scope: attribution.attribution_scope,
|
|
1887
1930
|
business_id: attribution.business_id || null,
|
|
1888
1931
|
workspace_id: attribution.workspace_id || null,
|
|
1889
1932
|
business_slug: attribution.business_slug || null,
|
|
1890
1933
|
workspace_template: attribution.workspace_template || null,
|
|
1934
|
+
computer_id: scopeFields.computer_id,
|
|
1891
1935
|
computer: attribution.computer || projection.workspace_name || workspaces[0]?.name || 'local',
|
|
1936
|
+
visibility: scopeFields.visibility,
|
|
1937
|
+
public_agentxp: scopeFields.public_agentxp,
|
|
1892
1938
|
operator: player,
|
|
1893
1939
|
privacy: {
|
|
1894
1940
|
raw_proofs_included: false,
|
|
@@ -1903,12 +1949,17 @@ function buildAgentXpSyncPacket(args = []) {
|
|
|
1903
1949
|
local_evidence: {
|
|
1904
1950
|
schema: 'atris.agentxp_local_evidence.v1',
|
|
1905
1951
|
workspace_root_hash: workspaceRootHash,
|
|
1952
|
+
scope: scopeFields.scope,
|
|
1953
|
+
org_id: scopeFields.org_id,
|
|
1906
1954
|
attribution_scope: attribution.attribution_scope,
|
|
1907
1955
|
business_id: attribution.business_id || null,
|
|
1908
1956
|
workspace_id: attribution.workspace_id || null,
|
|
1909
1957
|
business_slug: attribution.business_slug || null,
|
|
1910
1958
|
workspace_template: attribution.workspace_template || null,
|
|
1959
|
+
computer_id: scopeFields.computer_id,
|
|
1911
1960
|
computer: attribution.computer || null,
|
|
1961
|
+
visibility: scopeFields.visibility,
|
|
1962
|
+
public_agentxp: scopeFields.public_agentxp,
|
|
1912
1963
|
workspaces,
|
|
1913
1964
|
verified_workspace_count: asNumber(projection.verified_workspace_count, verifiedProjection(projection) ? 1 : 0),
|
|
1914
1965
|
receipts_count: receiptsCount,
|
|
@@ -1933,12 +1984,17 @@ function buildAgentXpSyncPacket(args = []) {
|
|
|
1933
1984
|
gm_projection: {
|
|
1934
1985
|
schema: 'atris.gm_xp_projection.v1',
|
|
1935
1986
|
workspace_root_hash: workspaceRootHash,
|
|
1987
|
+
scope: scopeFields.scope,
|
|
1988
|
+
org_id: scopeFields.org_id,
|
|
1936
1989
|
attribution_scope: attribution.attribution_scope,
|
|
1937
1990
|
business_id: attribution.business_id || null,
|
|
1938
1991
|
workspace_id: attribution.workspace_id || null,
|
|
1939
1992
|
business_slug: attribution.business_slug || null,
|
|
1940
1993
|
workspace_template: attribution.workspace_template || null,
|
|
1994
|
+
computer_id: scopeFields.computer_id,
|
|
1941
1995
|
computer: attribution.computer || null,
|
|
1996
|
+
visibility: scopeFields.visibility,
|
|
1997
|
+
public_agentxp: scopeFields.public_agentxp,
|
|
1942
1998
|
operator: player,
|
|
1943
1999
|
player_score: {
|
|
1944
2000
|
agent_xp: totalXp,
|