@datalayer/agent-runtimes 1.5.43 โ 1.5.44
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/chunks/1f30a-DxwAt2Ba.js +1 -0
- package/dist-embed/chunks/1f310-AqUM9a8q.js +1 -0
- package/dist-embed/chunks/1f324-8MHLOhTj.js +1 -0
- package/dist-embed/chunks/1f326-YSBr3aXI.js +1 -0
- package/dist-embed/chunks/1f327-Ie-nQBNO.js +1 -0
- package/dist-embed/chunks/1f33e-Cfl2WM63.js +1 -0
- package/dist-embed/chunks/1f372-3XLDlXkE.js +1 -0
- package/dist-embed/chunks/1f373-BPUJt2bp.js +1 -0
- package/dist-embed/chunks/1f39b-CSNtbAXr.js +1 -0
- package/dist-embed/chunks/1f3ab-BUCNQHz1.js +1 -0
- package/dist-embed/chunks/1f41b-Dre1z0gP.js +1 -0
- package/dist-embed/chunks/1f441-D8yah4C4.js +1 -0
- package/dist-embed/chunks/1f465-CPle6Hjq.js +1 -0
- package/dist-embed/chunks/1f4b9-aacFyckt.js +1 -0
- package/dist-embed/chunks/1f4be-DPAcAU4R.js +1 -0
- package/dist-embed/chunks/1f4c1-Ch6aJ0cj.js +1 -0
- package/dist-embed/chunks/1f4c2-Dx7BKmLO.js +1 -0
- package/dist-embed/chunks/1f4c4-CNvjvC5k.js +1 -0
- package/dist-embed/chunks/1f4d3-GTxRgjv7.js +1 -0
- package/dist-embed/chunks/1f4d6-COOZY-Q_.js +1 -0
- package/dist-embed/chunks/1f4dc-BhoW4cjD.js +1 -0
- package/dist-embed/chunks/1f4e1-DezU8ow-.js +1 -0
- package/dist-embed/chunks/1f4e2-DsStZsI-.js +1 -0
- package/dist-embed/chunks/1f4e7-BBi7c_zx.js +1 -0
- package/dist-embed/chunks/1f500-D9xRo-IT.js +1 -0
- package/dist-embed/chunks/1f501-CzKeDPcw.js +1 -0
- package/dist-embed/chunks/1f504-BYIHMoDP.js +1 -0
- package/dist-embed/chunks/1f52d-2QxCLKhU.js +1 -0
- package/dist-embed/chunks/1f552-4d0Y0kn7.js +1 -0
- package/dist-embed/chunks/1f58b-Cp8F_HBg.js +1 -0
- package/dist-embed/chunks/1f5b2-D6BUULuh.js +1 -0
- package/dist-embed/chunks/1f5c3-DjkgJLaz.js +1 -0
- package/dist-embed/chunks/1f5d1-C4Kpe4HL.js +1 -0
- package/dist-embed/chunks/1f5dc-DyLO7aB9.js +1 -0
- package/dist-embed/chunks/1f604-CEekcaYE.js +1 -0
- package/dist-embed/chunks/1f917-CyyS9fgf.js +1 -0
- package/dist-embed/chunks/1f9d1-200d-2696-D9eSB-0q.js +1 -0
- package/dist-embed/chunks/1fa79-DHhIZbWB.js +1 -0
- package/dist-embed/chunks/1fa9d-DUI9e77m.js +1 -0
- package/dist-embed/chunks/1fa9f-10ALsMaD.js +1 -0
- package/dist-embed/chunks/23f3-ASjqFsbT.js +1 -0
- package/dist-embed/chunks/2611-BnnmLm-K.js +1 -0
- package/dist-embed/chunks/2702-CfLyp35r.js +1 -0
- package/dist-embed/chunks/270f-CLwo30mk.js +1 -0
- package/dist-embed/chunks/2728-Qg6be-6p.js +1 -0
- package/dist-embed/chunks/2b1c-Uc1aRwAf.js +1 -0
- package/dist-embed/datalayer-app-main.js +66 -66
- package/lib/chat/ChatInline.js +43 -22
- package/lib/chat/base/ChatBase.js +43 -2
- package/lib/components/agents/AgentSummary.d.ts +2 -24
- package/lib/components/agents/AgentSummary.js +3 -19
- package/lib/hooks/useChat.js +110 -144
- package/lib/portable/activity.d.ts +78 -0
- package/lib/portable/activity.js +129 -0
- package/lib/portable/fixtures.d.ts +7 -0
- package/lib/portable/fixtures.js +50 -0
- package/lib/portable/index.d.ts +4 -1
- package/lib/portable/index.js +7 -1
- package/lib/portable/lifecycle.d.ts +77 -0
- package/lib/portable/lifecycle.js +135 -0
- package/lib/portable/runtimes.d.ts +68 -0
- package/lib/portable/runtimes.js +69 -0
- package/lib/voice/VoiceMenu.d.ts +2 -1
- package/lib/voice/VoiceMenu.js +2 -2
- package/lib/voice/chatVoice.d.ts +5 -2
- package/lib/voice/chatVoice.js +10 -4
- package/lib/voice/choices.d.ts +2 -0
- package/lib/voice/choices.js +6 -0
- package/lib/voice/index.d.ts +1 -0
- package/lib/voice/index.js +1 -0
- package/lib/voice/sayAloud.d.ts +25 -0
- package/lib/voice/sayAloud.js +34 -0
- package/lib/voice/serverHearing.d.ts +34 -2
- package/lib/voice/serverHearing.js +234 -6
- package/lib/voice/settings.d.ts +12 -0
- package/lib/voice/settings.js +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type RecordKind = 'session'
|
|
2
|
+
/** A run began: in progress until it answers (R-15). Not a step. */
|
|
3
|
+
| 'run' | 'tool_call' | 'decision' | 'check' | 'approval' | 'output' | 'feedback'
|
|
4
|
+
/** A turn of a conversation: what was asked, what it answered (V-16). */
|
|
5
|
+
| 'turn'
|
|
6
|
+
/** What it did, step by step (P-16); a harness's session, turn and plan events (SHIELD ยง6.4). */
|
|
7
|
+
| 'step'
|
|
8
|
+
/** What one of its channels was sent, or why not: `{channel, event, delivery, detail}` (R-37). */
|
|
9
|
+
| 'notification';
|
|
10
|
+
/** One entry of an application's record. */
|
|
11
|
+
export type RecordEntry = {
|
|
12
|
+
uid: string;
|
|
13
|
+
appUid: string;
|
|
14
|
+
sessionUid: string;
|
|
15
|
+
deploymentUid: string;
|
|
16
|
+
version: number;
|
|
17
|
+
kind: RecordKind;
|
|
18
|
+
summary: string;
|
|
19
|
+
payload: Record<string, unknown>;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
/** `test` for a session its tests ran (the Evals engine's); empty for real use. */
|
|
22
|
+
purpose: string;
|
|
23
|
+
};
|
|
24
|
+
/** An entry as ai-agents answers with it. */
|
|
25
|
+
export declare function entryOf(raw: Record<string, unknown>): RecordEntry;
|
|
26
|
+
/** How the run an entry ends ended: `answered`, `stopped`, `gone`; `''` for any other entry. */
|
|
27
|
+
export declare function runEndOf(entry: RecordEntry): string;
|
|
28
|
+
/** An entry in words: its summary, or how its run ended when its words are not kept. */
|
|
29
|
+
export declare function entrySaid(entry: RecordEntry): string;
|
|
30
|
+
/** A session in a sentence: how many calls, what stopped it, how it ended. */
|
|
31
|
+
export declare function sessionSentence(entries: readonly RecordEntry[]): string;
|
|
32
|
+
/** A run its schedule plans, as the scheduler says (R-15). */
|
|
33
|
+
export type ScheduledRun = {
|
|
34
|
+
deploymentUid: string;
|
|
35
|
+
appUid: string;
|
|
36
|
+
version: number;
|
|
37
|
+
/** Which of its triggers, by position in its Appspec. */
|
|
38
|
+
position: number;
|
|
39
|
+
cron: string;
|
|
40
|
+
description: string;
|
|
41
|
+
/** When it runs next; empty when the scheduler does not say. */
|
|
42
|
+
nextAt: string;
|
|
43
|
+
};
|
|
44
|
+
/** What an application, or all of a person's, is doing (R-15): real use only, its tests read apart. */
|
|
45
|
+
export type AppActivity = {
|
|
46
|
+
/** Sessions whose latest run has not answered yet, newest first: their run's start. */
|
|
47
|
+
inProgress: RecordEntry[];
|
|
48
|
+
/** Its live deployments' next runs, soonest first. */
|
|
49
|
+
scheduled: ScheduledRun[];
|
|
50
|
+
/** Why its schedules could not be read; empty when they were. */
|
|
51
|
+
scheduledProblem: string;
|
|
52
|
+
/** Its other sessions, newest first: their opening entries. */
|
|
53
|
+
completed: RecordEntry[];
|
|
54
|
+
/** The offset of the next page of completed sessions; `null` after the last. */
|
|
55
|
+
nextOffset: number | null;
|
|
56
|
+
};
|
|
57
|
+
/** `/apps/activity`'s answer, read. */
|
|
58
|
+
export declare function activityOf(body: Record<string, unknown>): AppActivity;
|
|
59
|
+
/** Pages as one: in progress and scheduled from the first, completed from all, the last page's next offset. */
|
|
60
|
+
export declare function mergeActivityPages(pages: readonly AppActivity[]): AppActivity;
|
|
61
|
+
/** What Activity says, on every client (checked against the vocabulary). */
|
|
62
|
+
export declare const ACTIVITY_WORDS: {
|
|
63
|
+
readonly inProgress: "In progress";
|
|
64
|
+
readonly scheduled: "Scheduled";
|
|
65
|
+
readonly completed: "Completed";
|
|
66
|
+
readonly working: "Working since";
|
|
67
|
+
readonly next: "next";
|
|
68
|
+
readonly wakes: "It also starts on its own when something happens:";
|
|
69
|
+
readonly nothing: "Nothing yet.";
|
|
70
|
+
};
|
|
71
|
+
/** What happens that starts it on its own, in words (LOOP W-03): its event triggers. */
|
|
72
|
+
export declare const wakesOn: (triggers: ReadonlyArray<{
|
|
73
|
+
type: string;
|
|
74
|
+
event?: string;
|
|
75
|
+
description?: string;
|
|
76
|
+
}> | undefined) => string[];
|
|
77
|
+
/** A scheduled run in words: what it does, and on which version. */
|
|
78
|
+
export declare const scheduledSays: (run: ScheduledRun) => string;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* What an application is doing (LOOP R-15), as ai-agents answers
|
|
7
|
+
* `/api/ai-agents/v1/apps/activity`, and its record's entries
|
|
8
|
+
* (`/apps/sessions`, `/apps/records`): read and said the same by the Studio
|
|
9
|
+
* and Datalayer Mobile (MOBILE M-015b). Pure: each client fetches with its own
|
|
10
|
+
* authentication and hands the body here.
|
|
11
|
+
*
|
|
12
|
+
* @module portable/activity
|
|
13
|
+
*/
|
|
14
|
+
import { RUN_END_WORDS } from './records';
|
|
15
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
16
|
+
const records = (value) => Array.isArray(value) ? value.filter(isRecord) : [];
|
|
17
|
+
const said = (value) => typeof value === 'string' ? value : value == null ? '' : String(value);
|
|
18
|
+
/** An entry as ai-agents answers with it. */
|
|
19
|
+
export function entryOf(raw) {
|
|
20
|
+
return {
|
|
21
|
+
uid: said(raw.uid),
|
|
22
|
+
appUid: said(raw.app_uid),
|
|
23
|
+
sessionUid: said(raw.session_uid),
|
|
24
|
+
deploymentUid: said(raw.deployment_uid),
|
|
25
|
+
version: Number(raw.version) || 0,
|
|
26
|
+
kind: (said(raw.kind) || 'output'),
|
|
27
|
+
summary: said(raw.summary),
|
|
28
|
+
payload: isRecord(raw.payload) ? raw.payload : {},
|
|
29
|
+
createdAt: said(raw.created_at),
|
|
30
|
+
purpose: said(raw.purpose),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** How the run an entry ends ended: `answered`, `stopped`, `gone`; `''` for any other entry. */
|
|
34
|
+
export function runEndOf(entry) {
|
|
35
|
+
const status = entry.kind === 'output' ? entry.payload.status : undefined;
|
|
36
|
+
return typeof status === 'string' && status in RUN_END_WORDS ? status : '';
|
|
37
|
+
}
|
|
38
|
+
/** An entry in words: its summary, or how its run ended when its words are not kept. */
|
|
39
|
+
export function entrySaid(entry) {
|
|
40
|
+
return entry.summary || RUN_END_WORDS[runEndOf(entry)] || '';
|
|
41
|
+
}
|
|
42
|
+
const plural = (n, word) => `${n} ${word}${n === 1 ? '' : 's'}`;
|
|
43
|
+
/** A session in a sentence: how many calls, what stopped it, how it ended. */
|
|
44
|
+
export function sessionSentence(entries) {
|
|
45
|
+
const calls = entries.filter(entry => entry.kind === 'tool_call').length;
|
|
46
|
+
const checks = entries.filter(entry => entry.kind === 'check');
|
|
47
|
+
const ends = entries.map(runEndOf).filter(Boolean);
|
|
48
|
+
const answers = ends.filter(end => end === 'answered').length;
|
|
49
|
+
const parts = [];
|
|
50
|
+
parts.push(calls === 0 ? 'No tool called' : plural(calls, 'tool call'));
|
|
51
|
+
if (checks.length) {
|
|
52
|
+
parts.push(`${plural(checks.length, 'step')} a check did not let pass`);
|
|
53
|
+
}
|
|
54
|
+
const unsent = entries.filter(entry => entry.kind === 'notification' && entry.payload.delivery !== 'sent');
|
|
55
|
+
if (unsent.length) {
|
|
56
|
+
parts.push(`${plural(unsent.length, 'notification')} not sent`);
|
|
57
|
+
}
|
|
58
|
+
if (ends[ends.length - 1] === 'stopped') {
|
|
59
|
+
parts.push('stopped');
|
|
60
|
+
}
|
|
61
|
+
else if (answers) {
|
|
62
|
+
parts.push(plural(answers, 'answer'));
|
|
63
|
+
}
|
|
64
|
+
return `${parts.join(', ')}.`;
|
|
65
|
+
}
|
|
66
|
+
/** `/apps/activity`'s answer, read. */
|
|
67
|
+
export function activityOf(body) {
|
|
68
|
+
return {
|
|
69
|
+
inProgress: records(body.in_progress).map(entryOf),
|
|
70
|
+
scheduled: records(body.scheduled).map(raw => ({
|
|
71
|
+
deploymentUid: said(raw.deployment_uid),
|
|
72
|
+
appUid: said(raw.app_uid),
|
|
73
|
+
version: Number(raw.version) || 0,
|
|
74
|
+
position: Number(raw.position) || 0,
|
|
75
|
+
cron: said(raw.cron),
|
|
76
|
+
description: said(raw.description),
|
|
77
|
+
nextAt: said(raw.next_at),
|
|
78
|
+
})),
|
|
79
|
+
scheduledProblem: said(body.scheduled_problem),
|
|
80
|
+
completed: records(body.completed).map(entryOf),
|
|
81
|
+
nextOffset: typeof body.next_offset === 'number' ? body.next_offset : null,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Pages as one: in progress and scheduled from the first, completed from all, the last page's next offset. */
|
|
85
|
+
export function mergeActivityPages(pages) {
|
|
86
|
+
const [first] = pages;
|
|
87
|
+
if (!first) {
|
|
88
|
+
return {
|
|
89
|
+
inProgress: [],
|
|
90
|
+
scheduled: [],
|
|
91
|
+
scheduledProblem: '',
|
|
92
|
+
completed: [],
|
|
93
|
+
nextOffset: null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const seen = new Set();
|
|
97
|
+
const completed = pages
|
|
98
|
+
.flatMap(page => page.completed)
|
|
99
|
+
.filter(entry => {
|
|
100
|
+
const key = entry.uid || entry.sessionUid;
|
|
101
|
+
if (seen.has(key)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
seen.add(key);
|
|
105
|
+
return true;
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
...first,
|
|
109
|
+
completed,
|
|
110
|
+
nextOffset: pages[pages.length - 1].nextOffset,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** What Activity says, on every client (checked against the vocabulary). */
|
|
114
|
+
export const ACTIVITY_WORDS = {
|
|
115
|
+
inProgress: 'In progress',
|
|
116
|
+
scheduled: 'Scheduled',
|
|
117
|
+
completed: 'Completed',
|
|
118
|
+
working: 'Working since',
|
|
119
|
+
next: 'next',
|
|
120
|
+
wakes: 'It also starts on its own when something happens:',
|
|
121
|
+
nothing: 'Nothing yet.',
|
|
122
|
+
};
|
|
123
|
+
/** What happens that starts it on its own, in words (LOOP W-03): its event triggers. */
|
|
124
|
+
export const wakesOn = (triggers) => (triggers ?? [])
|
|
125
|
+
.filter(trigger => trigger.type === 'event' && (trigger.description || trigger.event))
|
|
126
|
+
.map(trigger => trigger.description ||
|
|
127
|
+
`When ${String(trigger.event).replace(/_/g, ' ')}`);
|
|
128
|
+
/** A scheduled run in words: what it does, and on which version. */
|
|
129
|
+
export const scheduledSays = (run) => `${run.description || 'Its schedule'} (${run.cron}) ยท version ${run.version}`;
|
|
@@ -18,3 +18,10 @@ export declare function shieldDisplayFixtures(): {
|
|
|
18
18
|
terminal: Record<string, unknown>;
|
|
19
19
|
};
|
|
20
20
|
export declare function conversationFixture(): ConversationState;
|
|
21
|
+
/**
|
|
22
|
+
* `GET /api/ai-agents/v1/apps/activity`'s answer for one application: a
|
|
23
|
+
* session in progress, a scheduled run, a completed one ended by Stop, and a
|
|
24
|
+
* next page โ what the Studio's Activity and the phone's read alike (MOBILE
|
|
25
|
+
* M-015b).
|
|
26
|
+
*/
|
|
27
|
+
export declare function activityFixture(): Record<string, unknown>;
|
package/lib/portable/fixtures.js
CHANGED
|
@@ -118,3 +118,53 @@ export function conversationFixture() {
|
|
|
118
118
|
dropped: 3,
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* `GET /api/ai-agents/v1/apps/activity`'s answer for one application: a
|
|
123
|
+
* session in progress, a scheduled run, a completed one ended by Stop, and a
|
|
124
|
+
* next page โ what the Studio's Activity and the phone's read alike (MOBILE
|
|
125
|
+
* M-015b).
|
|
126
|
+
*/
|
|
127
|
+
export function activityFixture() {
|
|
128
|
+
return {
|
|
129
|
+
success: true,
|
|
130
|
+
in_progress: [
|
|
131
|
+
{
|
|
132
|
+
uid: 'e-run',
|
|
133
|
+
app_uid: 'app-1',
|
|
134
|
+
session_uid: 's-2',
|
|
135
|
+
deployment_uid: 'd-1',
|
|
136
|
+
version: 3,
|
|
137
|
+
kind: 'run',
|
|
138
|
+
summary: 'Triage the inbox',
|
|
139
|
+
payload: {},
|
|
140
|
+
created_at: '2026-10-16T08:00:00Z',
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
scheduled: [
|
|
144
|
+
{
|
|
145
|
+
deployment_uid: 'd-1',
|
|
146
|
+
app_uid: 'app-1',
|
|
147
|
+
version: 3,
|
|
148
|
+
position: 0,
|
|
149
|
+
cron: '0 8 * * 1-5',
|
|
150
|
+
description: 'Every weekday morning',
|
|
151
|
+
next_at: '2026-10-17T08:00:00Z',
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
scheduled_problem: '',
|
|
155
|
+
completed: [
|
|
156
|
+
{
|
|
157
|
+
uid: 'e-out',
|
|
158
|
+
app_uid: 'app-1',
|
|
159
|
+
session_uid: 's-1',
|
|
160
|
+
deployment_uid: 'd-1',
|
|
161
|
+
version: 3,
|
|
162
|
+
kind: 'output',
|
|
163
|
+
summary: '',
|
|
164
|
+
payload: { status: 'stopped' },
|
|
165
|
+
created_at: '2026-10-15T08:00:00Z',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
next_offset: 20,
|
|
169
|
+
};
|
|
170
|
+
}
|
package/lib/portable/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export { BROWSER_LIMITS, CUT_MARK, DEVICE_LIMITS, DIAGNOSTIC_LIMIT, emptyConvers
|
|
|
16
16
|
export { conversationEventsOf, sanitizeAssistantContent, snapshotOfMessages, type AdapterEvent, type SaidMessage, } from './adapterEvents';
|
|
17
17
|
export { PRESENCE_LINES, presenceOfConversation, presenceState, presenceToolOf, type PresenceState, type PresenceTool, } from './presence';
|
|
18
18
|
export { ANSWER_BELOW, ANSWER_COMPLETE, composerOf, droppedWords, ENDED_WORDS, messageLabel, OPENING_WORDS, presenceLine, showsQuestion, stepLine, TOOL_STATUS_WORDS, toolLabel, type ComposerProps, type ComposerState, type ConversationViewProps, type ErrorItem, type ErrorRowProps, type MessageItem, type MessageRowProps, type PresenceLineProps, type ProtocolDisplayProps, type QuestionCardProps, type StepItem, type StepRowProps, type ToolItem, type ToolRowProps, type TurnEndItem, type TurnEndRowProps, } from './views';
|
|
19
|
-
export { conversationFixture } from './fixtures';
|
|
19
|
+
export { activityFixture, conversationFixture } from './fixtures';
|
|
20
20
|
export { DISPLAY_META_KEY, displayLine, displayOfToolResult, PAP_CONFIRM_TYPE, PAP_HANDOFF_TOOL, PAP_OUTCOME_TYPE, PAP_REPLIES_TYPE, PAP_SIGN_IN_TYPE, protocolDisplayOf, replyAuthor, type ActionClass, type ProtocolDisplay, DIFF_LINES_LIMIT, SHIELD_DIFF_TYPE, SHIELD_TERMINAL_TYPE, languageOf, unifiedDiffLines, unifiedDiffText, type DiffLine, } from './displays';
|
|
21
21
|
export { shieldDisplayFixtures } from './fixtures';
|
|
22
22
|
export { isPapSignInTool, PAP_SIGN_IN_WORDS, readPapSignIn, safeSignInUrl, type PapSignInWaiting, } from './signIn';
|
|
@@ -24,5 +24,8 @@ export { DIRECT_MAX, DIRECT_WORDS, directAnswerOf, directAuthor, directClient, o
|
|
|
24
24
|
export { SIGN_IN_POLL_MS, SIGN_IN_STATUS_PATH, signInStandsOf, signInStatusClient, type SignInStands, } from './signInStatus';
|
|
25
25
|
export { emptyFields, fieldProblems, MAX_VALUE_LENGTH, PROTECTED_INPUT_WORDS, protectedInputClient, protectedRequestOf, ProtectedRequestGone, sentWords, submitBody, submitWords, ticketComplete, ticketOfPage, type ProtectedField, type ProtectedRequest, } from './protectedInput';
|
|
26
26
|
export { failureOf, otlpMetricsOf, RunMeter, type RunMeasure, type StreamFailure, } from './runMeasures';
|
|
27
|
+
export { ACTIVITY_WORDS, activityOf, entryOf, entrySaid, mergeActivityPages, runEndOf, scheduledSays, sessionSentence, wakesOn, type AppActivity, type RecordEntry, type RecordKind, type ScheduledRun, } from './activity';
|
|
28
|
+
export { deploymentEventLine, deploymentEventOf, notDeletedOf, resetBody, resetCountsOf, resetLines, stateChangeBody, stoppedWorkLine, stoppedWorkOf, type DeploymentEvent, type DeploymentEventKind, type DeploymentState, type ResetCounts, type StoppedWork, } from './lifecycle';
|
|
29
|
+
export { agentRuntimesOf, agentSummaryOfRuntime, CREATING_STATUSES, isAgentRuntime, isCreatingAgent, runtimeOf, type AgentRuntime, type AgentSummaryData, } from './runtimes';
|
|
27
30
|
export { agentRunClient, agentRuntimesUrlOf, appSessionsClient, RuntimeRefusal, type AgentRunClient, type AgentTurn, type AppSessionsClient, type RuntimeClientOptions, type SessionStart, type StreamOptions, } from './sessions';
|
|
28
31
|
export type { ChatMessage } from '../types/messages';
|
package/lib/portable/index.js
CHANGED
|
@@ -27,7 +27,7 @@ export { conversationEventsOf, sanitizeAssistantContent, snapshotOfMessages, } f
|
|
|
27
27
|
export { PRESENCE_LINES, presenceOfConversation, presenceState, presenceToolOf, } from './presence';
|
|
28
28
|
// One contract for every renderer of a conversation's components.
|
|
29
29
|
export { ANSWER_BELOW, ANSWER_COMPLETE, composerOf, droppedWords, ENDED_WORDS, messageLabel, OPENING_WORDS, presenceLine, showsQuestion, stepLine, TOOL_STATUS_WORDS, toolLabel, } from './views';
|
|
30
|
-
export { conversationFixture } from './fixtures';
|
|
30
|
+
export { activityFixture, conversationFixture } from './fixtures';
|
|
31
31
|
// The protocol displays a run's tool results carry (MOBILE M-037).
|
|
32
32
|
export { DISPLAY_META_KEY, displayLine, displayOfToolResult, PAP_CONFIRM_TYPE, PAP_HANDOFF_TOOL, PAP_OUTCOME_TYPE, PAP_REPLIES_TYPE, PAP_SIGN_IN_TYPE, protocolDisplayOf, replyAuthor,
|
|
33
33
|
// A coding agent's diff and terminal (SHIELD ยง4.3, SH-16).
|
|
@@ -42,5 +42,11 @@ export { SIGN_IN_POLL_MS, SIGN_IN_STATUS_PATH, signInStandsOf, signInStatusClien
|
|
|
42
42
|
export { emptyFields, fieldProblems, MAX_VALUE_LENGTH, PROTECTED_INPUT_WORDS, protectedInputClient, protectedRequestOf, ProtectedRequestGone, sentWords, submitBody, submitWords, ticketComplete, ticketOfPage, } from './protectedInput';
|
|
43
43
|
// How a streamed turn went, measured without its words (MOBILE M-036).
|
|
44
44
|
export { failureOf, otlpMetricsOf, RunMeter, } from './runMeasures';
|
|
45
|
+
// What an application is doing, and its record's entries (LOOP R-15, MOBILE M-015b).
|
|
46
|
+
export { ACTIVITY_WORDS, activityOf, entryOf, entrySaid, mergeActivityPages, runEndOf, scheduledSays, sessionSentence, wakesOn, } from './activity';
|
|
47
|
+
// A deployment's pause, resume and reset, and its recorded events (LOOP R-17, MOBILE M-041b).
|
|
48
|
+
export { deploymentEventLine, deploymentEventOf, notDeletedOf, resetBody, resetCountsOf, resetLines, stateChangeBody, stoppedWorkLine, stoppedWorkOf, } from './lifecycle';
|
|
49
|
+
// A person's agent runtimes, and an agent's summary (MOBILE M-014b).
|
|
50
|
+
export { agentRuntimesOf, agentSummaryOfRuntime, CREATING_STATUSES, isAgentRuntime, isCreatingAgent, runtimeOf, } from './runtimes';
|
|
45
51
|
// The runtime's routes a native client drives.
|
|
46
52
|
export { agentRunClient, agentRuntimesUrlOf, appSessionsClient, RuntimeRefusal, } from './sessions';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A deployment's lifecycle as its owner drives it (LOOP R-17, D-04): pause
|
|
3
|
+
* and resume one exact version, reset what it holds, and the events recorded
|
|
4
|
+
* with who did each. The requests' bodies, the answers read and the words
|
|
5
|
+
* said โ the same in the Studio and Datalayer Mobile (MOBILE M-041b). Pure:
|
|
6
|
+
* each client sends them with its own authentication.
|
|
7
|
+
*
|
|
8
|
+
* @module portable/lifecycle
|
|
9
|
+
*/
|
|
10
|
+
/** Whether a deployment answers now. */
|
|
11
|
+
export type DeploymentState = 'live' | 'paused';
|
|
12
|
+
/** Pause or resume, for one exact version: `PATCH /apps/deployments/{uid}`'s body. */
|
|
13
|
+
export declare const stateChangeBody: (version: number, state: DeploymentState) => {
|
|
14
|
+
version: number;
|
|
15
|
+
state: DeploymentState;
|
|
16
|
+
};
|
|
17
|
+
/** What pausing stopped, and what it could not, with why. */
|
|
18
|
+
export type StoppedWork = {
|
|
19
|
+
stopped: {
|
|
20
|
+
what: string;
|
|
21
|
+
runtime: string;
|
|
22
|
+
}[];
|
|
23
|
+
notStopped: {
|
|
24
|
+
what: string;
|
|
25
|
+
runtime: string;
|
|
26
|
+
why: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
export declare function stoppedWorkOf(raw: Record<string, unknown>): StoppedWork;
|
|
30
|
+
/** What pausing did, in a sentence. */
|
|
31
|
+
export declare function stoppedWorkLine(work: StoppedWork): string;
|
|
32
|
+
/** What a Reset deletes, counted for its confirmation. */
|
|
33
|
+
export type ResetCounts = {
|
|
34
|
+
conversations: number;
|
|
35
|
+
entries: number;
|
|
36
|
+
schedules: number;
|
|
37
|
+
/**
|
|
38
|
+
* Why its memories stay: they are its application's, not the
|
|
39
|
+
* deployment's (LOOP R-18) โ forgotten under *What it remembers*.
|
|
40
|
+
*/
|
|
41
|
+
memoriesNote: string;
|
|
42
|
+
};
|
|
43
|
+
export declare function resetCountsOf(raw: Record<string, unknown>): ResetCounts;
|
|
44
|
+
/** The Reset confirmed against the counts the person was shown: `POST โฆ/reset`'s body. */
|
|
45
|
+
export declare const resetBody: (counts: Pick<ResetCounts, "conversations" | "schedules">) => {
|
|
46
|
+
conversations: number;
|
|
47
|
+
schedules: number;
|
|
48
|
+
};
|
|
49
|
+
/** What a Reset could not delete, with why: `POST โฆ/reset`'s answer. */
|
|
50
|
+
export declare function notDeletedOf(body: Record<string, unknown>): {
|
|
51
|
+
what: string;
|
|
52
|
+
why: string;
|
|
53
|
+
}[];
|
|
54
|
+
/**
|
|
55
|
+
* What goes, as the confirmation lists it โ "12 conversations, 2
|
|
56
|
+
* schedules" โ and what does not, said apart.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resetLines(counts: ResetCounts): {
|
|
59
|
+
goes: string;
|
|
60
|
+
stays: string[];
|
|
61
|
+
};
|
|
62
|
+
/** What happened to a deployment, recorded with who did it (D-04, R-17). */
|
|
63
|
+
export type DeploymentEventKind = 'promoted' | 'rolled_back' | 'paused' | 'resumed' | 'reset';
|
|
64
|
+
/** Who promoted, rolled back, paused, resumed or reset a deployment, and when. */
|
|
65
|
+
export type DeploymentEvent = {
|
|
66
|
+
uid: string;
|
|
67
|
+
kind: DeploymentEventKind;
|
|
68
|
+
actor: string;
|
|
69
|
+
at: string;
|
|
70
|
+
details: Record<string, unknown>;
|
|
71
|
+
};
|
|
72
|
+
export declare function deploymentEventOf(raw: Record<string, unknown>): DeploymentEvent;
|
|
73
|
+
/**
|
|
74
|
+
* One event, in a line: "Paused by eric, 4 Oct 2026, 10:12", "Rolled back
|
|
75
|
+
* from version 3 to version 2 by eric, โฆ".
|
|
76
|
+
*/
|
|
77
|
+
export declare function deploymentEventLine(event: DeploymentEvent, locale?: string): string;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/** Pause or resume, for one exact version: `PATCH /apps/deployments/{uid}`'s body. */
|
|
6
|
+
export const stateChangeBody = (version, state) => {
|
|
7
|
+
if (!Number.isInteger(version) || version < 1) {
|
|
8
|
+
throw new Error(`A deployment's state is changed for one exact version: ${String(version)} is none.`);
|
|
9
|
+
}
|
|
10
|
+
return { version, state };
|
|
11
|
+
};
|
|
12
|
+
const listOf = (raw) => Array.isArray(raw)
|
|
13
|
+
? raw.filter(item => item && typeof item === 'object')
|
|
14
|
+
: [];
|
|
15
|
+
const said = (value) => typeof value === 'string' ? value : value == null ? '' : String(value);
|
|
16
|
+
const count = (value) => {
|
|
17
|
+
const n = Number(value);
|
|
18
|
+
return Number.isFinite(n) && n > 0 ? Math.trunc(n) : 0;
|
|
19
|
+
};
|
|
20
|
+
const plural = (n, word) => `${n} ${word}${n === 1 ? '' : 's'}`;
|
|
21
|
+
export function stoppedWorkOf(raw) {
|
|
22
|
+
return {
|
|
23
|
+
stopped: listOf(raw.stopped).map(item => ({
|
|
24
|
+
what: said(item.what),
|
|
25
|
+
runtime: said(item.runtime),
|
|
26
|
+
})),
|
|
27
|
+
notStopped: listOf(raw.not_stopped).map(item => ({
|
|
28
|
+
what: said(item.what),
|
|
29
|
+
runtime: said(item.runtime),
|
|
30
|
+
why: said(item.why),
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** What pausing did, in a sentence. */
|
|
35
|
+
export function stoppedWorkLine(work) {
|
|
36
|
+
const stopped = work.stopped.length;
|
|
37
|
+
const first = stopped === 0
|
|
38
|
+
? 'Paused: nothing was running.'
|
|
39
|
+
: `Paused: ${plural(stopped, 'session')} in progress stopped.`;
|
|
40
|
+
if (!work.notStopped.length) {
|
|
41
|
+
return first;
|
|
42
|
+
}
|
|
43
|
+
const missed = work.notStopped
|
|
44
|
+
.map(item => `${item.what}${item.runtime ? ` (${item.runtime})` : ''}: ${item.why}`)
|
|
45
|
+
.join(' ');
|
|
46
|
+
return `${first} Not stopped โ ${missed}`;
|
|
47
|
+
}
|
|
48
|
+
export function resetCountsOf(raw) {
|
|
49
|
+
return {
|
|
50
|
+
conversations: count(raw.conversations),
|
|
51
|
+
entries: count(raw.entries),
|
|
52
|
+
schedules: count(raw.schedules),
|
|
53
|
+
memoriesNote: typeof raw.memories_note === 'string' ? raw.memories_note : '',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** The Reset confirmed against the counts the person was shown: `POST โฆ/reset`'s body. */
|
|
57
|
+
export const resetBody = (counts) => ({
|
|
58
|
+
conversations: counts.conversations,
|
|
59
|
+
schedules: counts.schedules,
|
|
60
|
+
});
|
|
61
|
+
/** What a Reset could not delete, with why: `POST โฆ/reset`'s answer. */
|
|
62
|
+
export function notDeletedOf(body) {
|
|
63
|
+
return listOf(body.not_deleted).map(item => ({
|
|
64
|
+
what: said(item.what),
|
|
65
|
+
why: said(item.why),
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* What goes, as the confirmation lists it โ "12 conversations, 2
|
|
70
|
+
* schedules" โ and what does not, said apart.
|
|
71
|
+
*/
|
|
72
|
+
export function resetLines(counts) {
|
|
73
|
+
return {
|
|
74
|
+
goes: [
|
|
75
|
+
plural(counts.conversations, 'conversation'),
|
|
76
|
+
plural(counts.schedules, 'schedule'),
|
|
77
|
+
].join(', '),
|
|
78
|
+
stays: [
|
|
79
|
+
'The deployment, its address and the version it runs stay.',
|
|
80
|
+
...(counts.memoriesNote ? [counts.memoriesNote] : []),
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const EVENT_KINDS = [
|
|
85
|
+
'promoted',
|
|
86
|
+
'rolled_back',
|
|
87
|
+
'paused',
|
|
88
|
+
'resumed',
|
|
89
|
+
'reset',
|
|
90
|
+
];
|
|
91
|
+
export function deploymentEventOf(raw) {
|
|
92
|
+
if (!EVENT_KINDS.includes(raw.kind)) {
|
|
93
|
+
throw new Error(`A deployment's event of no known kind: ${String(raw.kind)}.`);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
uid: said(raw.uid),
|
|
97
|
+
kind: raw.kind,
|
|
98
|
+
actor: said(raw.actor_handle || raw.actor_uid || ''),
|
|
99
|
+
at: typeof raw.at === 'string' ? raw.at : '',
|
|
100
|
+
details: raw.details && typeof raw.details === 'object'
|
|
101
|
+
? raw.details
|
|
102
|
+
: {},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* One event, in a line: "Paused by eric, 4 Oct 2026, 10:12", "Rolled back
|
|
107
|
+
* from version 3 to version 2 by eric, โฆ".
|
|
108
|
+
*/
|
|
109
|
+
export function deploymentEventLine(event, locale) {
|
|
110
|
+
const from = count(event.details.from);
|
|
111
|
+
const to = count(event.details.to);
|
|
112
|
+
const moved = from && to ? ` from version ${from} to version ${to}` : '';
|
|
113
|
+
const verb = {
|
|
114
|
+
promoted: `Promoted${moved}`,
|
|
115
|
+
rolled_back: `Rolled back${moved}`,
|
|
116
|
+
paused: 'Paused',
|
|
117
|
+
resumed: 'Resumed',
|
|
118
|
+
reset: 'Reset',
|
|
119
|
+
}[event.kind];
|
|
120
|
+
const when = event.at
|
|
121
|
+
? new Date(event.at).toLocaleString(locale, {
|
|
122
|
+
dateStyle: 'medium',
|
|
123
|
+
timeStyle: 'short',
|
|
124
|
+
})
|
|
125
|
+
: '';
|
|
126
|
+
const deleted = event.details.deleted;
|
|
127
|
+
const what = event.kind === 'reset' && deleted
|
|
128
|
+
? ` โ ${plural(count(deleted.conversations), 'conversation')} and ${plural(count(deleted.schedules), 'schedule')} deleted`
|
|
129
|
+
: '';
|
|
130
|
+
// Paused by an owner of its owner's organization (I-09): said as such.
|
|
131
|
+
const forOrganization = event.kind === 'paused' && event.details.by === 'organization_owner'
|
|
132
|
+
? ', an owner of your organization'
|
|
133
|
+
: '';
|
|
134
|
+
return `${verb}${event.actor ? ` by ${event.actor}${forOrganization}` : ''}${when ? `, ${when}` : ''}${what}`;
|
|
135
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A person's agent runtimes as the runtimes service lists them
|
|
3
|
+
* (`GET /api/runtimes/v1/runtimes`), and an agent's summary and status as
|
|
4
|
+
* every client says them โ the web's `AgentSummary` badge and Datalayer
|
|
5
|
+
* Mobile's Agents (MOBILE M-014b). A raw runtime carries no application
|
|
6
|
+
* capabilities: no Rules, Protocols or Activity are read from it.
|
|
7
|
+
*
|
|
8
|
+
* @module portable/runtimes
|
|
9
|
+
*/
|
|
10
|
+
/** One agent runtime, as a client lists it. */
|
|
11
|
+
export type AgentRuntime = {
|
|
12
|
+
uid: string;
|
|
13
|
+
runtimeName: string;
|
|
14
|
+
givenName: string;
|
|
15
|
+
environment: string;
|
|
16
|
+
/** The agentspec it runs, when the runtime says. */
|
|
17
|
+
agentSpecId: string;
|
|
18
|
+
type: string;
|
|
19
|
+
state: string;
|
|
20
|
+
startedAt: string;
|
|
21
|
+
expiredAt: string;
|
|
22
|
+
/** Its Jupyter address, from which its agents' is read (`agentRuntimesUrlOf`). */
|
|
23
|
+
ingress: string;
|
|
24
|
+
};
|
|
25
|
+
/** A runtime of the runtimes service's answer. */
|
|
26
|
+
export declare function runtimeOf(raw: Record<string, unknown>): AgentRuntime;
|
|
27
|
+
/** The runtimes service's list, agent runtimes only: notebooks and terminals belong to the web workspace. */
|
|
28
|
+
export declare function agentRuntimesOf(body: Record<string, unknown>): AgentRuntime[];
|
|
29
|
+
/** An agent runtime, not a notebook's or a terminal's. */
|
|
30
|
+
export declare const isAgentRuntime: (runtime: AgentRuntime) => boolean;
|
|
31
|
+
/** What a summary of an agent says of it. */
|
|
32
|
+
export interface AgentSummaryData {
|
|
33
|
+
agentName: string;
|
|
34
|
+
location: string;
|
|
35
|
+
specId?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The framework turning this agent's loop, as its spec declares it โ
|
|
38
|
+
* `pydantic-ai` server-side, `vercel-ai` in the page.
|
|
39
|
+
*/
|
|
40
|
+
harness?: string;
|
|
41
|
+
/**
|
|
42
|
+
* The runtime variant the host chose: `<location>-<harness>`.
|
|
43
|
+
*
|
|
44
|
+
* Shown next to the harness rather than instead of it, because they answer
|
|
45
|
+
* different questions and can disagree: the harness is what the spec asked
|
|
46
|
+
* for, the variant is what it actually got.
|
|
47
|
+
*/
|
|
48
|
+
variant?: string;
|
|
49
|
+
status?: string;
|
|
50
|
+
baseUrl?: string;
|
|
51
|
+
sandboxBaseUrl?: string;
|
|
52
|
+
agentId?: string;
|
|
53
|
+
isReady?: boolean;
|
|
54
|
+
error?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Statuses that represent an agent actively being created/started. The spinner
|
|
58
|
+
* only shows for these; app-navigation states ("selected", "switching") and
|
|
59
|
+
* settled states ("ready", "running", ...) never spin.
|
|
60
|
+
*/
|
|
61
|
+
export declare const CREATING_STATUSES: ReadonlySet<string>;
|
|
62
|
+
/**
|
|
63
|
+
* An agent genuinely being created: it is not ready, has no id yet, and its
|
|
64
|
+
* status is one of creation or startup.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isCreatingAgent(summary: AgentSummaryData): boolean;
|
|
67
|
+
/** The summary of an agent the runtimes service lists: named as given, at Datalayer. */
|
|
68
|
+
export declare function agentSummaryOfRuntime(runtime: AgentRuntime): AgentSummaryData;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
6
|
+
const text = (value) => typeof value === 'string' ? value : '';
|
|
7
|
+
/** A runtime of the runtimes service's answer. */
|
|
8
|
+
export function runtimeOf(raw) {
|
|
9
|
+
const environment = isRecord(raw.environment) ? raw.environment : {};
|
|
10
|
+
return {
|
|
11
|
+
uid: text(raw.uid),
|
|
12
|
+
runtimeName: text(raw.runtime_name) || text(raw.pod_name),
|
|
13
|
+
givenName: text(raw.given_name),
|
|
14
|
+
environment: text(environment.title) ||
|
|
15
|
+
text(environment.name) ||
|
|
16
|
+
text(raw.environment_title) ||
|
|
17
|
+
text(raw.environment_name),
|
|
18
|
+
agentSpecId: text(raw.agent_spec_id) || text(raw.attached_agent_spec_id_s),
|
|
19
|
+
type: text(raw.type),
|
|
20
|
+
state: text(raw.state) || text(raw.status) || 'running',
|
|
21
|
+
startedAt: text(raw.started_at),
|
|
22
|
+
expiredAt: text(raw.expired_at),
|
|
23
|
+
ingress: text(raw.ingress),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** The runtimes service's list, agent runtimes only: notebooks and terminals belong to the web workspace. */
|
|
27
|
+
export function agentRuntimesOf(body) {
|
|
28
|
+
const listed = Array.isArray(body.runtimes) ? body.runtimes : [];
|
|
29
|
+
return listed
|
|
30
|
+
.filter(isRecord)
|
|
31
|
+
.map(runtimeOf)
|
|
32
|
+
.filter(runtime => runtime.runtimeName && isAgentRuntime(runtime));
|
|
33
|
+
}
|
|
34
|
+
/** An agent runtime, not a notebook's or a terminal's. */
|
|
35
|
+
export const isAgentRuntime = (runtime) => runtime.type === 'agent' ||
|
|
36
|
+
Boolean(runtime.agentSpecId) ||
|
|
37
|
+
/agent/i.test(runtime.environment);
|
|
38
|
+
/**
|
|
39
|
+
* Statuses that represent an agent actively being created/started. The spinner
|
|
40
|
+
* only shows for these; app-navigation states ("selected", "switching") and
|
|
41
|
+
* settled states ("ready", "running", ...) never spin.
|
|
42
|
+
*/
|
|
43
|
+
export const CREATING_STATUSES = new Set([
|
|
44
|
+
'creating',
|
|
45
|
+
'starting',
|
|
46
|
+
'launching',
|
|
47
|
+
'connecting',
|
|
48
|
+
'pending',
|
|
49
|
+
'resuming',
|
|
50
|
+
]);
|
|
51
|
+
/**
|
|
52
|
+
* An agent genuinely being created: it is not ready, has no id yet, and its
|
|
53
|
+
* status is one of creation or startup.
|
|
54
|
+
*/
|
|
55
|
+
export function isCreatingAgent(summary) {
|
|
56
|
+
return (!summary.isReady &&
|
|
57
|
+
!summary.agentId &&
|
|
58
|
+
CREATING_STATUSES.has((summary.status || '').toLowerCase()));
|
|
59
|
+
}
|
|
60
|
+
/** The summary of an agent the runtimes service lists: named as given, at Datalayer. */
|
|
61
|
+
export function agentSummaryOfRuntime(runtime) {
|
|
62
|
+
return {
|
|
63
|
+
agentName: runtime.givenName || runtime.runtimeName,
|
|
64
|
+
location: 'datalayer',
|
|
65
|
+
specId: runtime.agentSpecId || undefined,
|
|
66
|
+
status: runtime.state,
|
|
67
|
+
isReady: !CREATING_STATUSES.has(runtime.state.toLowerCase()),
|
|
68
|
+
};
|
|
69
|
+
}
|