@promptbook/cli 0.113.0-10 → 0.113.0-11

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.
Files changed (40) hide show
  1. package/apps/agents-server/src/app/admin/{code-runners/CodeRunnersClient.tsx → harness-auth/HarnessAuthClient.tsx} +98 -65
  2. package/apps/agents-server/src/app/admin/{code-runners → harness-auth}/page.tsx +4 -4
  3. package/apps/agents-server/src/app/api/admin/{code-runners → harness-auth}/authentication/route.ts +17 -17
  4. package/apps/agents-server/src/app/api/admin/{code-runners → harness-auth}/route.ts +13 -13
  5. package/apps/agents-server/src/app/layout.tsx +16 -0
  6. package/apps/agents-server/src/components/AdminTerminal/AdminTerminalCard.tsx +32 -24
  7. package/apps/agents-server/src/components/Footer/Footer.tsx +38 -15
  8. package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +5 -4
  9. package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +4 -1
  10. package/apps/agents-server/src/constants/harnessAuthRoutes.ts +20 -0
  11. package/apps/agents-server/src/languages/ServerTranslationKeys.ts +1 -1
  12. package/apps/agents-server/src/languages/translations/czech.yaml +2 -2
  13. package/apps/agents-server/src/languages/translations/english.yaml +1 -1
  14. package/apps/agents-server/src/utils/{codeRunnerAuthentication.ts → harnessAuthentication.ts} +72 -56
  15. package/apps/agents-server/src/utils/{codeRunnerConfiguration.ts → harnessConfiguration.ts} +18 -12
  16. package/apps/agents-server/src/utils/taskTerminal/resolveAdminTaskTerminalSession.ts +28 -5
  17. package/apps/agents-server/src/utils/vpsConfiguration.ts +3 -3
  18. package/apps/agents-server/src/utils/vpsSelfUpdate/readAgentsServerFooterVersion.ts +335 -0
  19. package/apps/agents-server/src/utils/vpsSelfUpdate/vpsSelfUpdateJobHistory.ts +107 -4
  20. package/esm/index.es.js +697 -591
  21. package/esm/index.es.js.map +1 -1
  22. package/esm/scripts/run-codex-prompts/common/sleepWithCountdown.d.ts +1 -0
  23. package/esm/scripts/run-codex-prompts/common/waitUntilWorldTimeDeadline.d.ts +17 -0
  24. package/esm/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +3 -16
  25. package/esm/src/utils/agents/terminalAgentAvatarVisual.d.ts +94 -0
  26. package/esm/src/utils/agents/terminalAgentAvatarVisual.test.d.ts +1 -0
  27. package/esm/src/version.d.ts +1 -1
  28. package/package.json +1 -1
  29. package/src/other/templates/getTemplatesPipelineCollection.ts +790 -807
  30. package/src/utils/agents/terminalAgentAvatarVisual.ts +261 -0
  31. package/src/version.ts +2 -2
  32. package/src/versions.txt +1 -0
  33. package/umd/index.umd.js +697 -591
  34. package/umd/index.umd.js.map +1 -1
  35. package/umd/scripts/run-codex-prompts/common/sleepWithCountdown.d.ts +1 -0
  36. package/umd/scripts/run-codex-prompts/common/waitUntilWorldTimeDeadline.d.ts +17 -0
  37. package/umd/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +3 -16
  38. package/umd/src/utils/agents/terminalAgentAvatarVisual.d.ts +94 -0
  39. package/umd/src/utils/agents/terminalAgentAvatarVisual.test.d.ts +1 -0
  40. package/umd/src/version.d.ts +1 -1
@@ -1,7 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF, NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA } from '@/config';
4
- import { CLAIM, NAME, PROMPTBOOK_ENGINE_VERSION } from '@promptbook-local/core';
3
+ import { CLAIM, NAME } from '@promptbook-local/core';
5
4
  import { useServerLanguage } from '../ServerLanguage/ServerLanguageProvider';
6
5
  import { HeadlessLink } from '../_utils/headlessParam';
7
6
  import { getCommitFooterEmoji } from './getCommitFooterEmoji';
@@ -16,6 +15,18 @@ export type FooterLink = {
16
15
  url: string;
17
16
  };
18
17
 
18
+ /**
19
+ * Lightweight precomputed version metadata rendered in the footer.
20
+ *
21
+ * @private Internal to `apps/agents-server`
22
+ */
23
+ export type FooterVersionInfo = {
24
+ label: string;
25
+ url: string;
26
+ commitSha: string | null;
27
+ releasedAtLabel: string | null;
28
+ };
29
+
19
30
  /**
20
31
  * Configuration passed to `Footer` from the layout container.
21
32
  *
@@ -23,6 +34,7 @@ export type FooterLink = {
23
34
  */
24
35
  type FooterProps = {
25
36
  extraLinks?: FooterLink[];
37
+ version: FooterVersionInfo;
26
38
  };
27
39
 
28
40
  /**
@@ -31,8 +43,9 @@ type FooterProps = {
31
43
  * @private Internal to `apps/agents-server`
32
44
  */
33
45
  export function Footer(props: FooterProps) {
34
- const { extraLinks = [] } = props;
46
+ const { extraLinks = [], version } = props;
35
47
  const { t } = useServerLanguage();
48
+ const versionText = version.releasedAtLabel ? `${version.label}, ${version.releasedAtLabel}` : version.label;
36
49
 
37
50
  return (
38
51
  <footer className="border-t border-gray-200 bg-white dark:border-slate-700 dark:bg-slate-950">
@@ -46,7 +59,9 @@ export function Footer(props: FooterProps) {
46
59
 
47
60
  {/* Products */}
48
61
  <div className="space-y-4">
49
- <h3 className="font-bold text-gray-900 dark:text-slate-100">{t('footer.productSectionTitle')}</h3>
62
+ <h3 className="font-bold text-gray-900 dark:text-slate-100">
63
+ {t('footer.productSectionTitle')}
64
+ </h3>
50
65
  <ul className="space-y-2 text-sm">
51
66
  <li>
52
67
  <HeadlessLink href="/get-started" className="text-gray-500 hover:text-gray-900">
@@ -81,7 +96,9 @@ export function Footer(props: FooterProps) {
81
96
 
82
97
  {/* Company */}
83
98
  <div className="space-y-4">
84
- <h3 className="font-bold text-gray-900 dark:text-slate-100">{t('footer.companySectionTitle')}</h3>
99
+ <h3 className="font-bold text-gray-900 dark:text-slate-100">
100
+ {t('footer.companySectionTitle')}
101
+ </h3>
85
102
  <ul className="space-y-2 text-sm">
86
103
  <li>
87
104
  <a
@@ -111,7 +128,9 @@ export function Footer(props: FooterProps) {
111
128
 
112
129
  {/* Social */}
113
130
  <div className="space-y-4">
114
- <h3 className="font-bold text-gray-900 dark:text-slate-100">{t('footer.connectSectionTitle')}</h3>
131
+ <h3 className="font-bold text-gray-900 dark:text-slate-100">
132
+ {t('footer.connectSectionTitle')}
133
+ </h3>
115
134
  <ul className="space-y-2 text-sm">
116
135
  <li>
117
136
  <a
@@ -145,7 +164,9 @@ export function Footer(props: FooterProps) {
145
164
  {/* Extra Links from Metadata */}
146
165
  {extraLinks.length > 0 && (
147
166
  <div className="space-y-4">
148
- <h3 className="font-bold text-gray-900 dark:text-slate-100">{t('footer.linksSectionTitle')}</h3>
167
+ <h3 className="font-bold text-gray-900 dark:text-slate-100">
168
+ {t('footer.linksSectionTitle')}
169
+ </h3>
149
170
  <ul className="space-y-2 text-sm">
150
171
  {extraLinks.map((link, index) => (
151
172
  <li key={index}>
@@ -168,16 +189,18 @@ export function Footer(props: FooterProps) {
168
189
  <p>
169
190
  &copy; {new Date().getFullYear()} Promptbook
170
191
  <br />
171
- {t('footer.allRightsReserved')}
172
- <br />
173
- {t('footer.madeInCzechRepublic', { emoji: getCommitFooterEmoji(NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA) })}
192
+ {t('footer.madeInCzechRepublic', { emoji: getCommitFooterEmoji(version.commitSha) })}
174
193
  {/* <- TODO: !!!!!!!! Put here Prague outline */}
175
194
  </p>
176
- <p className="mt-2 text-xs text-gray-400">
177
- {t('footer.engineVersion')} {PROMPTBOOK_ENGINE_VERSION}{' '}
178
- {{ main: 'live', preview: 'preview', production: 'prod', lts: 'lts' }[
179
- NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF!
180
- ] || NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF}
195
+ <p className="mt-2 text-xs text-gray-400 dark:text-slate-500">
196
+ <a
197
+ href={version.url}
198
+ className="hover:text-gray-600 dark:hover:text-slate-300"
199
+ target="_blank"
200
+ rel="noopener noreferrer"
201
+ >
202
+ {versionText}
203
+ </a>
181
204
  </p>
182
205
  </div>
183
206
  {/*
@@ -52,6 +52,7 @@ import {
52
52
  type LucideIcon,
53
53
  } from 'lucide-react';
54
54
  import { createElement } from 'react';
55
+ import { HARNESS_AUTH_ADMIN_PATH } from '../../constants/harnessAuthRoutes';
55
56
  import type { ServerTranslationKey } from '../../languages/ServerTranslationKeys';
56
57
  import type { ShibbolethAuthenticationMenuStatus } from '../../constants/shibbolethAuth';
57
58
  import type { ChatFeedbackMode } from '../../utils/chatFeedbackMode';
@@ -102,7 +103,7 @@ type SystemMenuItemHref =
102
103
  | '/admin/update'
103
104
  | '/admin/database'
104
105
  | '/admin/logs'
105
- | '/admin/code-runners'
106
+ | typeof HARNESS_AUTH_ADMIN_PATH
106
107
  | '/admin/cli-access'
107
108
  | '/admin/models'
108
109
  | '/admin/metadata'
@@ -178,7 +179,7 @@ const SYSTEM_MENU_ICON_BY_HREF: Record<SystemMenuItemHref, LucideIcon> = {
178
179
  '/admin/update': RefreshCw,
179
180
  '/admin/database': Database,
180
181
  '/admin/logs': ScrollText,
181
- '/admin/code-runners': TerminalSquare,
182
+ [HARNESS_AUTH_ADMIN_PATH]: TerminalSquare,
182
183
  '/admin/cli-access': Terminal,
183
184
  '/admin/models': Bot,
184
185
  '/admin/metadata': FileJson,
@@ -411,8 +412,8 @@ export function buildHeaderSystemMenuItems({
411
412
  href: '/admin/logs',
412
413
  } as SubMenuItem,
413
414
  {
414
- label: translate('header.codeRunners'),
415
- href: '/admin/code-runners',
415
+ label: translate('header.harnessAuth'),
416
+ href: HARNESS_AUTH_ADMIN_PATH,
416
417
  } as SubMenuItem,
417
418
  {
418
419
  label: translate('header.cliAccess'),
@@ -18,7 +18,7 @@ import { ClientVersionMismatchListener } from '../ClientVersion/ClientVersionMis
18
18
  import { ChatEnterBehaviorPreferencesProvider } from '../ChatEnterBehavior/ChatEnterBehaviorPreferencesProvider';
19
19
  import { HomepageOptimisticNavigation } from '../Homepage/HomepageOptimisticNavigation';
20
20
  import { FileUploadAvailabilityProvider } from '../FileUploadAvailability/FileUploadAvailabilityContext';
21
- import { Footer, type FooterLink } from '../Footer/Footer';
21
+ import { Footer, type FooterLink, type FooterVersionInfo } from '../Footer/Footer';
22
22
  import { ActiveAgentBreadcrumbProvider } from '../Header/ActiveAgentBreadcrumbContext';
23
23
  import { Header } from '../Header/Header';
24
24
  import { MobileMenuHoistingProvider } from '../Header/MobileMenuHoistingContext';
@@ -50,6 +50,7 @@ type LayoutWrapperProps = {
50
50
  agentNaming: AgentNaming;
51
51
  isFooterShown: boolean;
52
52
  footerLinks: Array<FooterLink>;
53
+ footerVersion: FooterVersionInfo;
53
54
  federatedServers: Array<{ url: string; title: string }>;
54
55
  isExperimental: boolean;
55
56
  feedbackMode: ChatFeedbackMode;
@@ -102,6 +103,7 @@ export function LayoutWrapper({
102
103
  agentNaming,
103
104
  isFooterShown,
104
105
  footerLinks,
106
+ footerVersion,
105
107
  federatedServers,
106
108
  isExperimental,
107
109
  feedbackMode,
@@ -212,6 +214,7 @@ export function LayoutWrapper({
212
214
  !isFooterHiddenOnPage && (
213
215
  <Footer
214
216
  extraLinks={footerLinks}
217
+ version={footerVersion}
215
218
  />
216
219
  )}
217
220
  </div>
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Admin page path for configuring standalone harness authentication.
3
+ *
4
+ * @private internal route constant for Agents Server Harness Auth UI
5
+ */
6
+ export const HARNESS_AUTH_ADMIN_PATH = '/admin/harness-auth';
7
+
8
+ /**
9
+ * Admin API path for configuring standalone harness authentication.
10
+ *
11
+ * @private internal route constant for Agents Server Harness Auth UI
12
+ */
13
+ export const HARNESS_AUTH_API_PATH = '/api/admin/harness-auth';
14
+
15
+ /**
16
+ * Admin API path for the interactive harness authentication terminal.
17
+ *
18
+ * @private internal route constant for Agents Server Harness Auth UI
19
+ */
20
+ export const HARNESS_AUTHENTICATION_API_PATH = `${HARNESS_AUTH_API_PATH}/authentication`;
@@ -147,7 +147,7 @@ export const SERVER_TRANSLATION_KEYS = [
147
147
  'header.update',
148
148
  'header.database',
149
149
  'header.logs',
150
- 'header.codeRunners',
150
+ 'header.harnessAuth',
151
151
  'header.cliAccess',
152
152
  'header.models',
153
153
  'header.openApiDocumentation',
@@ -141,7 +141,7 @@ header.resourceMonitor: Monitoring zdrojů
141
141
  header.update: Aktualizace
142
142
  header.database: Databáze
143
143
  header.logs: Logy
144
- header.codeRunners: Code runnery
144
+ header.harnessAuth: Přihlášení harnessu
145
145
  header.cliAccess: CLI přístup
146
146
  header.models: Modely
147
147
  header.openApiDocumentation: Dokumentace OpenAPI
@@ -381,7 +381,7 @@ footer.logosAndBranding: Loga a vizuální identita
381
381
  footer.connectSectionTitle: Spojte se s námi
382
382
  footer.linksSectionTitle: Odkazy
383
383
  footer.allRightsReserved: Všechna práva vyhrazena.
384
- footer.madeInCzechRepublic: Vytvořeno s {emoji} v České republice.
384
+ footer.madeInCzechRepublic: Vytvořeno s {emoji} v Evropě.
385
385
  footer.engineVersion: Verze jádra Promptbooku
386
386
  forbidden.title: 403 Zakázáno
387
387
  forbidden.message: Nemáte oprávnění k přístupu na tuto stránku.
@@ -143,7 +143,7 @@ header.resourceMonitor: Resource monitor
143
143
  header.update: Update
144
144
  header.database: Database
145
145
  header.logs: Logs
146
- header.codeRunners: Code runners
146
+ header.harnessAuth: Harness Auth
147
147
  header.cliAccess: CLI Access
148
148
  header.models: Models
149
149
  header.openApiDocumentation: OpenAPI Documentation
@@ -11,21 +11,23 @@ import {
11
11
  } from './interactiveTerminalSession';
12
12
 
13
13
  /**
14
- * Serializable snapshot of one interactive code-runner authentication session.
14
+ * Serializable snapshot of one interactive harness authentication session.
15
+ *
16
+ * @private internal utility of Agents Server Harness Auth
15
17
  */
16
- export type CodeRunnerAuthenticationSessionSnapshot = {
18
+ export type HarnessAuthenticationSessionSnapshot = {
17
19
  /**
18
20
  * Session identifier used by the browser UI.
19
21
  */
20
22
  readonly id: string;
21
23
 
22
24
  /**
23
- * Runner being authenticated.
25
+ * Harness being authenticated.
24
26
  */
25
- readonly agent: string;
27
+ readonly harness: string;
26
28
 
27
29
  /**
28
- * Whether the interactive runner process is still active.
30
+ * Whether the interactive harness process is still active.
29
31
  */
30
32
  readonly isRunning: boolean;
31
33
 
@@ -57,8 +59,10 @@ export type CodeRunnerAuthenticationSessionSnapshot = {
57
59
 
58
60
  /**
59
61
  * Browser stream callbacks used by one subscribed UI client.
62
+ *
63
+ * @private internal utility of Agents Server Harness Auth
60
64
  */
61
- export type CodeRunnerAuthenticationSessionSubscriber = {
65
+ export type HarnessAuthenticationSessionSubscriber = {
62
66
  /**
63
67
  * Called whenever new terminal output arrives.
64
68
  */
@@ -67,27 +71,29 @@ export type CodeRunnerAuthenticationSessionSubscriber = {
67
71
  /**
68
72
  * Called once the session exits.
69
73
  */
70
- readonly onExit: (event: { readonly type: 'exit'; readonly snapshot: CodeRunnerAuthenticationSessionSnapshot }) => void;
74
+ readonly onExit: (event: { readonly type: 'exit'; readonly snapshot: HarnessAuthenticationSessionSnapshot }) => void;
71
75
  };
72
76
 
73
77
  /**
74
- * Starts a streamed authentication session for the currently configured standalone runner.
78
+ * Starts a streamed authentication session for the currently configured standalone harness.
75
79
  *
76
- * @param agent - Runner identifier stored in `.env`.
77
- * @returns Existing running session for the same runner or a new one.
80
+ * @param harness - Harness identifier stored in `.env`.
81
+ * @returns Existing running session for the same harness or a new one.
82
+ *
83
+ * @private internal utility of Agents Server Harness Auth
78
84
  */
79
- export async function startCodeRunnerAuthenticationSession(
80
- agent: string,
81
- ): Promise<CodeRunnerAuthenticationSessionSnapshot> {
85
+ export async function startHarnessAuthenticationSession(
86
+ harness: string,
87
+ ): Promise<HarnessAuthenticationSessionSnapshot> {
82
88
  const scriptPath = await resolveVpsInstallerScriptPath();
83
89
  if (!scriptPath) {
84
90
  throw new Error('The VPS installer script could not be found on this server.');
85
91
  }
86
92
 
87
- return toRequiredCodeRunnerAuthenticationSessionSnapshot(
93
+ return toRequiredHarnessAuthenticationSessionSnapshot(
88
94
  startInteractiveTerminalSession({
89
- sessionKey: buildCodeRunnerAuthenticationSessionKey(agent),
90
- title: `${agent} authentication`,
95
+ sessionKey: buildHarnessAuthenticationSessionKey(harness),
96
+ title: `${harness} authentication`,
91
97
  command: 'bash',
92
98
  arguments: [scriptPath, 'authenticate-runner'],
93
99
  env: createVpsInstallerCommandEnvironment({
@@ -95,26 +101,28 @@ export async function startCodeRunnerAuthenticationSession(
95
101
  isProcessRestartEnabled: false,
96
102
  }),
97
103
  metadata: {
98
- agent,
104
+ harness,
99
105
  },
100
- unavailableErrorMessage: 'Interactive code-runner authentication is available only on the Linux VPS runtime.',
106
+ unavailableErrorMessage: 'Interactive harness authentication is available only on the Linux VPS runtime.',
101
107
  }),
102
- agent,
108
+ harness,
103
109
  );
104
110
  }
105
111
 
106
112
  /**
107
- * Returns the latest known authentication session for a runner.
113
+ * Returns the latest known authentication session for a harness.
108
114
  *
109
- * @param agent - Runner identifier.
115
+ * @param harness - Harness identifier.
110
116
  * @returns Serializable session snapshot or `null`.
117
+ *
118
+ * @private internal utility of Agents Server Harness Auth
111
119
  */
112
- export function getLatestCodeRunnerAuthenticationSession(
113
- agent: string,
114
- ): CodeRunnerAuthenticationSessionSnapshot | null {
115
- return toCodeRunnerAuthenticationSessionSnapshot(
116
- getLatestInteractiveTerminalSession(buildCodeRunnerAuthenticationSessionKey(agent)),
117
- agent,
120
+ export function getLatestHarnessAuthenticationSession(
121
+ harness: string,
122
+ ): HarnessAuthenticationSessionSnapshot | null {
123
+ return toHarnessAuthenticationSessionSnapshot(
124
+ getLatestInteractiveTerminalSession(buildHarnessAuthenticationSessionKey(harness)),
125
+ harness,
118
126
  );
119
127
  }
120
128
 
@@ -123,11 +131,13 @@ export function getLatestCodeRunnerAuthenticationSession(
123
131
  *
124
132
  * @param sessionId - Session identifier.
125
133
  * @returns Serializable session snapshot or `null`.
134
+ *
135
+ * @private internal utility of Agents Server Harness Auth
126
136
  */
127
- export function getCodeRunnerAuthenticationSession(
137
+ export function getHarnessAuthenticationSession(
128
138
  sessionId: string,
129
- ): CodeRunnerAuthenticationSessionSnapshot | null {
130
- return toCodeRunnerAuthenticationSessionSnapshot(getInteractiveTerminalSession(sessionId));
139
+ ): HarnessAuthenticationSessionSnapshot | null {
140
+ return toHarnessAuthenticationSessionSnapshot(getInteractiveTerminalSession(sessionId));
131
141
  }
132
142
 
133
143
  /**
@@ -136,17 +146,19 @@ export function getCodeRunnerAuthenticationSession(
136
146
  * @param sessionId - Session identifier.
137
147
  * @param subscriber - Stream callbacks.
138
148
  * @returns Cleanup callback.
149
+ *
150
+ * @private internal utility of Agents Server Harness Auth
139
151
  */
140
- export function subscribeToCodeRunnerAuthenticationSession(
152
+ export function subscribeToHarnessAuthenticationSession(
141
153
  sessionId: string,
142
- subscriber: CodeRunnerAuthenticationSessionSubscriber,
154
+ subscriber: HarnessAuthenticationSessionSubscriber,
143
155
  ): (() => void) | null {
144
156
  return subscribeToInteractiveTerminalSession(sessionId, {
145
157
  onOutput: subscriber.onOutput,
146
158
  onExit: ({ snapshot }) =>
147
159
  subscriber.onExit({
148
160
  type: 'exit',
149
- snapshot: toRequiredCodeRunnerAuthenticationSessionSnapshot(snapshot),
161
+ snapshot: toRequiredHarnessAuthenticationSessionSnapshot(snapshot),
150
162
  }),
151
163
  });
152
164
  }
@@ -157,12 +169,14 @@ export function subscribeToCodeRunnerAuthenticationSession(
157
169
  * @param sessionId - Session identifier.
158
170
  * @param input - Raw text to write to stdin.
159
171
  * @returns Updated session snapshot.
172
+ *
173
+ * @private internal utility of Agents Server Harness Auth
160
174
  */
161
- export function writeCodeRunnerAuthenticationSessionInput(
175
+ export function writeHarnessAuthenticationSessionInput(
162
176
  sessionId: string,
163
177
  input: string,
164
- ): CodeRunnerAuthenticationSessionSnapshot {
165
- return toRequiredCodeRunnerAuthenticationSessionSnapshot(writeInteractiveTerminalSessionInput(sessionId, input));
178
+ ): HarnessAuthenticationSessionSnapshot {
179
+ return toRequiredHarnessAuthenticationSessionSnapshot(writeInteractiveTerminalSessionInput(sessionId, input));
166
180
  }
167
181
 
168
182
  /**
@@ -170,41 +184,43 @@ export function writeCodeRunnerAuthenticationSessionInput(
170
184
  *
171
185
  * @param sessionId - Session identifier.
172
186
  * @returns Updated session snapshot.
187
+ *
188
+ * @private internal utility of Agents Server Harness Auth
173
189
  */
174
- export function stopCodeRunnerAuthenticationSession(
190
+ export function stopHarnessAuthenticationSession(
175
191
  sessionId: string,
176
- ): CodeRunnerAuthenticationSessionSnapshot {
177
- return toRequiredCodeRunnerAuthenticationSessionSnapshot(stopInteractiveTerminalSession(sessionId));
192
+ ): HarnessAuthenticationSessionSnapshot {
193
+ return toRequiredHarnessAuthenticationSessionSnapshot(stopInteractiveTerminalSession(sessionId));
178
194
  }
179
195
 
180
196
  /**
181
- * Builds the stable logical session key for one runner authentication terminal.
197
+ * Builds the stable logical session key for one harness authentication terminal.
182
198
  *
183
- * @param agent - Runner identifier.
199
+ * @param harness - Harness identifier.
184
200
  * @returns Stable session key.
185
201
  */
186
- function buildCodeRunnerAuthenticationSessionKey(agent: string): string {
187
- return `code-runner-authentication:${agent}`;
202
+ function buildHarnessAuthenticationSessionKey(harness: string): string {
203
+ return `harness-authentication:${harness}`;
188
204
  }
189
205
 
190
206
  /**
191
- * Converts one generic terminal snapshot into the runner-specific browser shape.
207
+ * Converts one generic terminal snapshot into the harness-specific browser shape.
192
208
  *
193
209
  * @param session - Generic terminal snapshot.
194
- * @param fallbackAgent - Agent name used when older sessions miss metadata.
195
- * @returns Runner-specific snapshot or `null`.
210
+ * @param fallbackHarness - Harness name used when older sessions miss metadata.
211
+ * @returns Harness-specific snapshot or `null`.
196
212
  */
197
- function toCodeRunnerAuthenticationSessionSnapshot(
213
+ function toHarnessAuthenticationSessionSnapshot(
198
214
  session: InteractiveTerminalSessionSnapshot | null,
199
- fallbackAgent = '',
200
- ): CodeRunnerAuthenticationSessionSnapshot | null {
215
+ fallbackHarness = '',
216
+ ): HarnessAuthenticationSessionSnapshot | null {
201
217
  if (!session) {
202
218
  return null;
203
219
  }
204
220
 
205
221
  return {
206
222
  id: session.id,
207
- agent: session.metadata.agent || fallbackAgent,
223
+ harness: session.metadata.harness || session.metadata.agent || fallbackHarness,
208
224
  isRunning: session.isRunning,
209
225
  output: session.output,
210
226
  startedAt: session.startedAt,
@@ -215,16 +231,16 @@ function toCodeRunnerAuthenticationSessionSnapshot(
215
231
  }
216
232
 
217
233
  /**
218
- * Converts one generic terminal snapshot into a required runner-specific snapshot.
234
+ * Converts one generic terminal snapshot into a required harness-specific snapshot.
219
235
  *
220
236
  * @param session - Generic terminal snapshot.
221
- * @returns Runner-specific snapshot.
237
+ * @returns Harness-specific snapshot.
222
238
  */
223
- function toRequiredCodeRunnerAuthenticationSessionSnapshot(
239
+ function toRequiredHarnessAuthenticationSessionSnapshot(
224
240
  session: InteractiveTerminalSessionSnapshot | null,
225
- fallbackAgent = '',
226
- ): CodeRunnerAuthenticationSessionSnapshot {
227
- const mappedSession = toCodeRunnerAuthenticationSessionSnapshot(session, fallbackAgent);
241
+ fallbackHarness = '',
242
+ ): HarnessAuthenticationSessionSnapshot {
243
+ const mappedSession = toHarnessAuthenticationSessionSnapshot(session, fallbackHarness);
228
244
 
229
245
  if (!mappedSession) {
230
246
  throw new Error('Authentication session was not found.');
@@ -5,13 +5,15 @@ import { listVpsEnvironmentVariables } from './vpsConfiguration';
5
5
  const execFileAsync = promisify(execFile);
6
6
 
7
7
  /**
8
- * Saved standalone VPS code-runner configuration exposed to the admin UI.
8
+ * Saved standalone VPS harness configuration exposed to the admin UI.
9
+ *
10
+ * @private internal utility of Agents Server Harness Auth
9
11
  */
10
- export type ConfiguredCodeRunner = {
12
+ export type ConfiguredHarness = {
11
13
  /**
12
- * Runner identifier persisted in `.env`.
14
+ * Harness identifier persisted in `.env`.
13
15
  */
14
- readonly agent: string;
16
+ readonly harness: string;
15
17
 
16
18
  /**
17
19
  * Model identifier persisted in `.env`.
@@ -25,11 +27,13 @@ export type ConfiguredCodeRunner = {
25
27
  };
26
28
 
27
29
  /**
28
- * Reads the currently configured standalone VPS code runner from managed environment variables.
30
+ * Reads the currently configured standalone VPS harness from managed environment variables.
31
+ *
32
+ * @returns Saved harness settings with fallback defaults.
29
33
  *
30
- * @returns Saved code-runner settings with fallback defaults.
34
+ * @private internal utility of Agents Server Harness Auth
31
35
  */
32
- export async function readConfiguredCodeRunner(): Promise<ConfiguredCodeRunner> {
36
+ export async function readConfiguredHarness(): Promise<ConfiguredHarness> {
33
37
  const snapshot = await listVpsEnvironmentVariables();
34
38
  const environmentByKey = Object.fromEntries(snapshot.variables.map((variable) => [variable.key, variable.value])) as Record<
35
39
  string,
@@ -37,20 +41,22 @@ export async function readConfiguredCodeRunner(): Promise<ConfiguredCodeRunner>
37
41
  >;
38
42
 
39
43
  return {
40
- agent: environmentByKey.PTBK_HARNESS || process.env.PTBK_HARNESS || process.env.PTBK_AGENT || 'github-copilot',
44
+ harness: environmentByKey.PTBK_HARNESS || process.env.PTBK_HARNESS || process.env.PTBK_AGENT || 'github-copilot',
41
45
  model: environmentByKey.PTBK_MODEL || process.env.PTBK_MODEL || 'gpt-5.4',
42
46
  thinkingLevel: environmentByKey.PTBK_THINKING_LEVEL || process.env.PTBK_THINKING_LEVEL || 'xhigh',
43
47
  };
44
48
  }
45
49
 
46
50
  /**
47
- * Resolves a short runner-authentication status for the configured runner.
51
+ * Resolves a short authentication status for the configured harness.
48
52
  *
49
- * @param agent - Runner id.
53
+ * @param harness - Harness id.
50
54
  * @returns Human-readable status.
55
+ *
56
+ * @private internal utility of Agents Server Harness Auth
51
57
  */
52
- export async function resolveCodeRunnerStatus(agent: string): Promise<string> {
53
- if (agent !== 'github-copilot') {
58
+ export async function resolveHarnessStatus(harness: string): Promise<string> {
59
+ if (harness !== 'github-copilot') {
54
60
  return 'Status check is currently available for GitHub Copilot CLI only.';
55
61
  }
56
62
 
@@ -9,7 +9,6 @@ import { getLocalUserChatJobMetadata } from '../localChatRunner/LocalUserChatJob
9
9
  import { resolveLocalAgentRootPath } from '../localChatRunner/ensureLocalAgentFolder';
10
10
  import { listPagePreviewBrowserAdminTasks } from '../pagePreviewBrowserSessions';
11
11
  import {
12
- readVpsSelfUpdateJobSnapshot,
13
12
  readVpsSelfUpdateJobTaskSnapshots,
14
13
  readVpsSelfUpdateLogFileContent,
15
14
  } from '../vpsSelfUpdate';
@@ -308,8 +307,8 @@ async function resolveVpsSelfUpdateTaskTerminalSession(taskId: string): Promise<
308
307
  return null;
309
308
  }
310
309
 
311
- const latestJob = await readVpsSelfUpdateJobSnapshot();
312
- const isLatestJob = resolveVpsSelfUpdateJobIdentity(latestJob) === jobIdentity;
310
+ const latestJob = jobSnapshots[0] ?? null;
311
+ const isLatestJob = latestJob !== null && resolveVpsSelfUpdateJobIdentity(latestJob) === jobIdentity;
313
312
  const output = isLatestJob
314
313
  ? (await readVpsSelfUpdateLogFileContent()) || ''
315
314
  : createArchivedVpsSelfUpdateLogPlaceholder(job);
@@ -330,13 +329,27 @@ async function resolveVpsSelfUpdateTaskTerminalSession(taskId: string): Promise<
330
329
  subscribe: createPolledTaskTerminalLogFileSubscribe({
331
330
  session,
332
331
  readOutput: async () => {
333
- const latestJobSnapshot = await readVpsSelfUpdateJobSnapshot();
332
+ const latestJobSnapshot = await readLatestVpsSelfUpdateTaskSnapshot();
333
+ if (!latestJobSnapshot) {
334
+ return null;
335
+ }
336
+
334
337
  const isStillLatestJob = resolveVpsSelfUpdateJobIdentity(latestJobSnapshot) === jobIdentity;
335
338
 
336
339
  return isStillLatestJob ? (await readVpsSelfUpdateLogFileContent()) || '' : null;
337
340
  },
338
341
  resolveExitSnapshot: async (knownOutput) => {
339
- const latestJobSnapshot = await readVpsSelfUpdateJobSnapshot();
342
+ const latestJobSnapshot = await readLatestVpsSelfUpdateTaskSnapshot();
343
+ if (!latestJobSnapshot) {
344
+ return {
345
+ ...session,
346
+ isRunning: false,
347
+ output: knownOutput,
348
+ finishedAt: new Date().toISOString(),
349
+ exitCode: 1,
350
+ };
351
+ }
352
+
340
353
  const isStillLatestJob = resolveVpsSelfUpdateJobIdentity(latestJobSnapshot) === jobIdentity;
341
354
 
342
355
  if (isStillLatestJob && latestJobSnapshot.status === 'running') {
@@ -355,6 +368,16 @@ async function resolveVpsSelfUpdateTaskTerminalSession(taskId: string): Promise<
355
368
  };
356
369
  }
357
370
 
371
+ /**
372
+ * Reads the latest restart-aware standalone VPS self-update task snapshot.
373
+ *
374
+ * @returns Latest self-update task snapshot or `null` when no task snapshot is persisted.
375
+ */
376
+ async function readLatestVpsSelfUpdateTaskSnapshot(): Promise<VpsSelfUpdateJobSnapshot | null> {
377
+ const jobSnapshots = await readVpsSelfUpdateJobTaskSnapshots();
378
+ return jobSnapshots[0] ?? null;
379
+ }
380
+
358
381
  /**
359
382
  * Explains why an archived self-update run has no full installer log anymore.
360
383
  *
@@ -284,12 +284,12 @@ export async function applyVpsRuntimeConfiguration(
284
284
  }
285
285
 
286
286
  /**
287
- * Installs/configures the selected local code runner through the shared VPS installer script.
287
+ * Installs/configures the selected local harness through the shared VPS installer script.
288
288
  *
289
289
  * @returns Command output or a skipped reason when not running on a Linux VPS.
290
290
  */
291
- export async function applyVpsCodeRunnerConfiguration(): Promise<VpsCommandResult> {
292
- return runVpsInstallerCommand('apply-runner', 'VPS code-runner configuration can only be applied on Linux.');
291
+ export async function applyVpsHarnessConfiguration(): Promise<VpsCommandResult> {
292
+ return runVpsInstallerCommand('apply-runner', 'VPS harness configuration can only be applied on Linux.');
293
293
  }
294
294
 
295
295
  /**