@timurproko/a1 0.1.8-dev.271 → 0.1.8-dev.279

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 (36) hide show
  1. package/dist/composition/owned-ui.js +6 -0
  2. package/dist/contracts/owned-ui/index.d.ts +1 -0
  3. package/dist/contracts/owned-ui/index.js +1 -0
  4. package/dist/contracts/owned-ui/model.d.ts +52 -0
  5. package/dist/contracts/owned-ui/prompt-suggestions.d.ts +3 -0
  6. package/dist/contracts/owned-ui/prompt-suggestions.js +41 -0
  7. package/dist/contracts/owned-ui/validation.d.ts +5 -1
  8. package/dist/contracts/owned-ui/validation.js +67 -3
  9. package/dist/foundation/supervision/server.d.ts +11 -0
  10. package/dist/foundation/supervision/server.js +38 -5
  11. package/dist/integrations/pi/components/owned-editor-ux.d.ts +2 -0
  12. package/dist/integrations/pi/components/owned-editor-ux.js +5 -3
  13. package/dist/integrations/pi/components/shell-editor-autocomplete.js +15 -0
  14. package/dist/integrations/pi/components/shell-shared-facade.d.ts +8 -0
  15. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +15 -2
  16. package/dist/integrations/pi/components/upstream/components/owned-editor.js +102 -3
  17. package/dist/integrations/pi/engine/adapter.d.ts +3 -2
  18. package/dist/integrations/pi/engine/adapter.js +106 -2
  19. package/dist/integrations/pi/engine/conformance.d.ts +1 -1
  20. package/dist/integrations/pi/engine/conformance.js +2 -2
  21. package/dist/integrations/pi/engine/workflow-controllers.d.ts +1 -1
  22. package/dist/integrations/pi/session-ui/index.d.ts +1 -0
  23. package/dist/integrations/pi/session-ui/index.js +1 -0
  24. package/dist/integrations/pi/session-ui/prompt-suggestion-controller.d.ts +27 -0
  25. package/dist/integrations/pi/session-ui/prompt-suggestion-controller.js +132 -0
  26. package/dist/integrations/pi/session-ui/session-shell-root.d.ts +12 -1
  27. package/dist/integrations/pi/session-ui/session-shell-root.js +27 -1
  28. package/dist/integrations/pi/session-ui/session-shell.js +86 -2
  29. package/dist/native/darwin-arm64/manifest.json +1 -1
  30. package/dist/native/linux-x64/manifest.json +1 -1
  31. package/dist/native/win32-x64/manifest.json +2 -2
  32. package/dist/native/win32-x64/process-guardian.exe +0 -0
  33. package/dist/ui/settings/declarations.d.ts +1 -1
  34. package/dist/ui/settings/declarations.js +9 -1
  35. package/dist/ui/settings/migrations.js +7 -0
  36. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { PRODUCT_TEXT } from "../../../product-identity.js";
2
+ import { ContextualPromptSuggestionController } from "./prompt-suggestion-controller.js";
2
3
  import { MOUSE_TRACKING_OFF, MOUSE_TRACKING_ON, parseMouseInput, readVisibleHyperlinks } from "../../../ui/components/index.js";
3
4
  import { PINNED_PI_HIDDEN_COMMAND_NAMES, PINNED_PI_WORKFLOW_COMMAND_NAMES, } from "../engine/index.js";
4
5
  import { createPiExtensionUiBridge, createPiQueuedInputStatus, createPiShellArmin, createPiShellAuthProviderSelector, createPiShellChangelog, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellEditor, createPiShellExtensionSelector, createPiShellFooter, createPiShellHeader, createPiShellHotkeys, createPiShellLoadedResources, createPiShellLoginDialog, createPiShellModelSelector, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionInfo, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellStatus, createPiShellTranscriptComponent, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, onPiThemeChange, piTheme, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellStatusText, renderPiShellTranscriptBlock, } from "../components/index.js";
@@ -16,6 +17,8 @@ export class OwnedUiSessionShell {
16
17
  #cwd;
17
18
  #listeners = new Set();
18
19
  #unsubscribe;
20
+ #unsubscribePromptSuggestions;
21
+ #promptSuggestions;
19
22
  #extensionBridge;
20
23
  #stopped;
21
24
  #resolveStopped;
@@ -44,9 +47,11 @@ export class OwnedUiSessionShell {
44
47
  #lastEscapeTime = 0;
45
48
  #activeLoginDialog;
46
49
  #sessionGeneration;
50
+ #suggestionModelKey;
47
51
  constructor(options) {
48
52
  this.backend = options.backend;
49
53
  this.#sessionGeneration = this.backend.sessionGeneration;
54
+ this.#suggestionModelKey = modelKey(this.backend.view());
50
55
  this.#cwd = options.cwd;
51
56
  this.#routeHost = options.routeHost ?? null;
52
57
  this.#customViewport = options.sessionLayout === "custom-viewport";
@@ -59,6 +64,7 @@ export class OwnedUiSessionShell {
59
64
  let damageTerminal;
60
65
  let streamPresentation;
61
66
  let pendingClipboardWrite = Promise.resolve();
67
+ let promptSuggestionController = null;
62
68
  this.root = new OwnedUiSessionShellRoot(this.backend.view(), options.cwd, {
63
69
  getColumns: () => runtime?.viewport().columns ?? options.terminal?.columns ?? 80,
64
70
  getRows: () => runtime?.viewport().rows ?? options.terminal?.rows ?? 24,
@@ -84,6 +90,9 @@ export class OwnedUiSessionShell {
84
90
  onMessageCopy: () => { void this.runWorkflow({ command: "copy", argument: "" }); },
85
91
  onFollowUp: () => { void this.queueFollowUp(); },
86
92
  onDequeue: () => this.restoreQueuedInput(),
93
+ onEditorChange: () => promptSuggestionController?.invalidate(),
94
+ onPromptSuggestionAccepted: () => promptSuggestionController?.accept(),
95
+ onInputSurfaceChanged: () => promptSuggestionController?.invalidate(),
87
96
  onCopyText: text => {
88
97
  runtime?.writeControl(`\u001b]52;c;${Buffer.from(text, "utf8").toString("base64")}\u0007`);
89
98
  const write = options.clipboard === undefined
@@ -163,6 +172,26 @@ export class OwnedUiSessionShell {
163
172
  ? new StreamPresentationCoalescer(() => this.runtime.requestRender(), presentationInterval)
164
173
  : new StreamPresentationCoalescer(() => this.runtime.requestRender(), presentationInterval, options.streamPresentation.scheduler);
165
174
  this.#streamPresentation = streamPresentation;
175
+ const promptSuggestionOptions = this.#customViewport ? options.promptSuggestions : undefined;
176
+ promptSuggestionController = promptSuggestionOptions === undefined ? null : new ContextualPromptSuggestionController({
177
+ generator: promptSuggestionOptions.generator,
178
+ enabled: promptSuggestionOptions.enabled(),
179
+ surface: {
180
+ canPresent: identity => this.#canPresentPromptSuggestion(identity),
181
+ present: text => {
182
+ if (!this.root.canPresentPromptSuggestion())
183
+ return false;
184
+ this.root.setPromptSuggestion(text);
185
+ return true;
186
+ },
187
+ clear: () => this.root.setPromptSuggestion(null),
188
+ requestRender: () => this.runtime.requestRender(),
189
+ },
190
+ });
191
+ this.#promptSuggestions = promptSuggestionController;
192
+ this.#unsubscribePromptSuggestions = promptSuggestionOptions === undefined
193
+ ? () => { }
194
+ : promptSuggestionOptions.onChange(enabled => this.#promptSuggestions?.setEnabled(enabled));
166
195
  const initialPiSettings = this.backend.pinnedSettingsSnapshot();
167
196
  this.runtime.setHardwareCursor(initialPiSettings.showHardwareCursor);
168
197
  this.runtime.setClearOnShrink(initialPiSettings.clearOnShrink);
@@ -308,15 +337,48 @@ export class OwnedUiSessionShell {
308
337
  // Performance: a streamed chunk names one block, and touching only that block is what keeps the
309
338
  // cost of a chunk the same in a long session as in a new one. Everything else
310
339
  // resynchronizes the view, which is cheap next to re-reading the transcript.
311
- if (event.type === "agent-run-started")
340
+ if (event.type === "agent-run-started") {
341
+ this.#promptSuggestions?.invalidate();
312
342
  this.root.resumeViewportFollowing();
313
- if (event.type === "assistant-message-completed")
343
+ }
344
+ if (event.type === "assistant-message-completed") {
314
345
  this.root.noteCompletedAssistantMessage();
346
+ if (event.model !== null) {
347
+ this.#promptSuggestions?.consider({
348
+ sessionId: event.sessionId,
349
+ sessionGeneration: event.sessionGeneration,
350
+ runSequence: event.runSequence,
351
+ responseSequence: event.responseSequence,
352
+ model: event.model,
353
+ }, event.successful
354
+ && event.stopReason === "stop"
355
+ && !event.toolContinuation
356
+ && event.assistantMessageCount >= 2
357
+ && this.root.canPreparePromptSuggestion());
358
+ }
359
+ }
315
360
  const semanticOnly = event.type === "agent-run-started" || event.type === "assistant-message-completed";
316
361
  const view = event.type === "transcript-block" && this.#sessionGeneration === this.backend.sessionGeneration
317
362
  ? this.#syncBlock(event.block)
318
363
  : semanticOnly ? this.view() : this.#syncView();
319
364
  this.#syncTerminalProgress(view);
365
+ const currentModelKey = modelKey(view);
366
+ if (this.backend.sessionGeneration !== this.#sessionGeneration || currentModelKey !== this.#suggestionModelKey) {
367
+ this.#promptSuggestions?.invalidate();
368
+ this.#suggestionModelKey = currentModelKey;
369
+ }
370
+ if (event.type === "status" && /^(Retrying|Compacting)/.test(event.status.workingMessage ?? "")) {
371
+ this.#promptSuggestions?.invalidate();
372
+ }
373
+ if (event.type === "agent-run-settled" && event.model !== null) {
374
+ this.#promptSuggestions?.settle({
375
+ sessionId: event.sessionId,
376
+ sessionGeneration: event.sessionGeneration,
377
+ runSequence: event.runSequence,
378
+ responseSequence: event.responseSequence,
379
+ model: event.model,
380
+ });
381
+ }
320
382
  if (view.lifecycle === "ready" && this.#compactionQueue.length > 0)
321
383
  void this.#flushCompactionQueue();
322
384
  if (event.type === "session-lifecycle" && event.lifecycle === "stopped")
@@ -328,6 +390,14 @@ export class OwnedUiSessionShell {
328
390
  view() {
329
391
  return this.backend.view();
330
392
  }
393
+ #canPresentPromptSuggestion(identity) {
394
+ const view = this.view();
395
+ return !this.#disposed
396
+ && identity.sessionId === view.sessionId
397
+ && identity.sessionGeneration === this.backend.sessionGeneration
398
+ && modelKey(view) === `${identity.model.providerId}/${identity.model.modelId}`
399
+ && this.root.canPresentPromptSuggestion();
400
+ }
331
401
  damagePresentationDecision() {
332
402
  return this.#damageTerminal?.lastDecision ?? null;
333
403
  }
@@ -351,6 +421,7 @@ export class OwnedUiSessionShell {
351
421
  return this.#stopped;
352
422
  }
353
423
  async submit(text) {
424
+ this.#promptSuggestions?.invalidate();
354
425
  const displayInput = text.trim();
355
426
  if (!displayInput)
356
427
  return { outcome: "completed", diagnostic: null };
@@ -406,6 +477,7 @@ export class OwnedUiSessionShell {
406
477
  });
407
478
  }
408
479
  async clearOrExit(now = Date.now()) {
480
+ this.#promptSuggestions?.invalidate();
409
481
  if (now - this.#lastClearTime < 500)
410
482
  return this.shutdown();
411
483
  this.root.editor.setText("");
@@ -414,6 +486,7 @@ export class OwnedUiSessionShell {
414
486
  return { outcome: "completed", diagnostic: null };
415
487
  }
416
488
  async interrupt(now = Date.now()) {
489
+ this.#promptSuggestions?.invalidate();
417
490
  if (this.view().lifecycle === "busy")
418
491
  return this.abort();
419
492
  if (this.root.editor.getText().trim().length > 0) {
@@ -441,15 +514,19 @@ export class OwnedUiSessionShell {
441
514
  return this.#execute(this.#simple("abort"));
442
515
  }
443
516
  async retry() {
517
+ this.#promptSuggestions?.invalidate();
444
518
  return this.#execute(this.#simple("retry"));
445
519
  }
446
520
  async compact() {
521
+ this.#promptSuggestions?.invalidate();
447
522
  return this.#execute(this.#simple("compact"));
448
523
  }
449
524
  async newSession() {
525
+ this.#promptSuggestions?.invalidate();
450
526
  return this.#execute(this.#simple("new-session"));
451
527
  }
452
528
  async resumeSession(sessionPath) {
529
+ this.#promptSuggestions?.invalidate();
453
530
  return this.#execute({
454
531
  type: "resume-session",
455
532
  correlationId: this.#correlation("resume"),
@@ -458,6 +535,7 @@ export class OwnedUiSessionShell {
458
535
  });
459
536
  }
460
537
  async setModel(providerId, modelId) {
538
+ this.#promptSuggestions?.invalidate();
461
539
  return this.#execute({
462
540
  type: "set-model",
463
541
  correlationId: this.#correlation("model"),
@@ -1008,6 +1086,8 @@ export class OwnedUiSessionShell {
1008
1086
  this.#setPointerReporting(false, true);
1009
1087
  this.#removeViewportPreInput();
1010
1088
  this.#streamPresentation.dispose();
1089
+ this.#promptSuggestions?.dispose();
1090
+ this.#unsubscribePromptSuggestions();
1011
1091
  this.#unsubscribeSettings();
1012
1092
  const exitMode = this.backend.disposed
1013
1093
  ? this.#fullscreenExitOutput
@@ -1059,6 +1139,7 @@ export class OwnedUiSessionShell {
1059
1139
  this.#streamPresentation.noteImmediatePresentation();
1060
1140
  const view = this.view();
1061
1141
  if (this.backend.sessionGeneration !== this.#sessionGeneration) {
1142
+ this.#promptSuggestions?.invalidate();
1062
1143
  this.#sessionGeneration = this.backend.sessionGeneration;
1063
1144
  this.#activeLoginDialog = undefined;
1064
1145
  this.#extensionBridge.reset();
@@ -1385,6 +1466,9 @@ function modelReference(model) {
1385
1466
  function rejected(diagnostic) {
1386
1467
  return { outcome: "rejected", diagnostic };
1387
1468
  }
1469
+ function modelKey(view) {
1470
+ return view.activeModel === null ? "" : `${view.activeModel.providerId}/${view.activeModel.modelId}`;
1471
+ }
1388
1472
  function workflowAdapterResult(result) {
1389
1473
  if (result.outcome === "completed")
1390
1474
  return { outcome: "completed", diagnostic: null };
@@ -5,7 +5,7 @@
5
5
  "platform": "darwin",
6
6
  "architecture": "arm64",
7
7
  "capability": "supported",
8
- "builtAt": "2026-09-06T15:05:45.656Z",
8
+ "builtAt": "2026-09-07T08:48:09.287Z",
9
9
  "artifact": {
10
10
  "filename": "process-guardian",
11
11
  "sha256": "dc03605e5780e2aeebb4ecafd62868dc673e22ddd38b024a369aff704ff136dc",
@@ -5,7 +5,7 @@
5
5
  "platform": "linux",
6
6
  "architecture": "x64",
7
7
  "capability": "supported",
8
- "builtAt": "2026-09-06T15:05:42.977Z",
8
+ "builtAt": "2026-09-07T08:48:08.596Z",
9
9
  "artifact": {
10
10
  "filename": "process-guardian",
11
11
  "sha256": "ee8a00eaaf79c707459bbbfb52518e9739314967049fbe5fa625f36ce33db9ee",
@@ -5,10 +5,10 @@
5
5
  "platform": "win32",
6
6
  "architecture": "x64",
7
7
  "capability": "supported",
8
- "builtAt": "2026-09-06T15:06:12.448Z",
8
+ "builtAt": "2026-09-07T08:48:53.798Z",
9
9
  "artifact": {
10
10
  "filename": "process-guardian.exe",
11
- "sha256": "7cca17597d89ae0dad9cd14114acc0795f688d54f6580b897463fba11af479ca",
11
+ "sha256": "ec965cf23ffb3dd4f8db9b265c620c3bbc078418a6f7e330bdcbf4d0055f6393",
12
12
  "size": 177664
13
13
  },
14
14
  "provenance": {
@@ -1,4 +1,4 @@
1
- export declare const OWNED_UI_SETTINGS_VERSION = 3;
1
+ export declare const OWNED_UI_SETTINGS_VERSION = 4;
2
2
  export type OwnedUiSettingValue = string | number | boolean;
3
3
  export type OwnedUiSettingApplication = "live" | "restart";
4
4
  export interface OwnedUiSettingDeclaration {
@@ -1,4 +1,4 @@
1
- export const OWNED_UI_SETTINGS_VERSION = 3;
1
+ export const OWNED_UI_SETTINGS_VERSION = 4;
2
2
  const MAX_ID_LENGTH = 64;
3
3
  const ID_PATTERN = /^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/;
4
4
  const SCROLL_SECTION = Object.freeze({ id: "scroll", title: "Scroll" });
@@ -30,6 +30,14 @@ export const OWNED_UI_SETTING_DECLARATIONS = Object.freeze([
30
30
  defaultValue: "normal",
31
31
  allowedValues: Object.freeze(["normal", "fast", "high"]),
32
32
  }),
33
+ Object.freeze({
34
+ id: "promptSuggestions",
35
+ label: "Prompt suggestions",
36
+ description: "Predict likely next prompts with one additional background request using the selected model.",
37
+ application: "live",
38
+ defaultValue: true,
39
+ allowedValues: Object.freeze([true, false]),
40
+ }),
33
41
  ]);
34
42
  export function assertOwnedUiSettingDeclarations(declarations) {
35
43
  const seen = new Set();
@@ -22,6 +22,13 @@ export const OWNED_UI_SETTINGS_MIGRATIONS = Object.freeze([
22
22
  : { ...values };
23
23
  },
24
24
  }),
25
+ Object.freeze({
26
+ to: 4,
27
+ description: "Introduce contextual prompt suggestions with an enabled default.",
28
+ migrate(values) {
29
+ return { ...values };
30
+ },
31
+ }),
25
32
  ]);
26
33
  export function assertOwnedUiSettingsMigrations(migrations, currentVersion = OWNED_UI_SETTINGS_VERSION) {
27
34
  const firstProduced = currentVersion - migrations.length + 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timurproko/a1",
3
- "version": "0.1.8-dev.271",
3
+ "version": "0.1.8-dev.279",
4
4
  "description": "Standalone terminal workspace for supervised native and managed agents",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.13.0",