Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions spx-gui/src/components/copilot/CopilotRound.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue'
import { RoundState, type Round } from './copilot'
import { provideCopilotRound } from './context'
import MarkdownView from './MarkdownView.vue'
import BaseFailed from './feedback/BaseFailed.vue'
import BaseCancelled from './feedback/BaseCancelled.vue'
Expand All @@ -13,6 +14,9 @@ const props = defineProps<{
isLastRound: boolean
}>()

// Let markdown elements rendered in this round (e.g. code guides) know which round they belong to.
provideCopilotRound({ round: props.round, isLastRound: () => props.isLastRound })

const feedbackProps = computed(() => ({
round: props.round,
isLastRound: props.isLastRound
Expand Down
21 changes: 20 additions & 1 deletion spx-gui/src/components/copilot/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { inject, provide, type InjectionKey } from 'vue'
import type { Copilot } from './copilot'
import type { Copilot, Round } from './copilot'

const copilotInjectionKey: InjectionKey<Copilot> = Symbol('copilot')

Expand All @@ -12,3 +12,22 @@ export function useCopilot(): Copilot {
export function provideCopilot(copilot: Copilot) {
return provide(copilotInjectionKey, copilot)
}

/** Context describing the copilot round a markdown element is rendered within. */
export interface CopilotRoundContext {
/** The round this content belongs to. */
round: Round
/** Whether this is the latest round in the session. */
isLastRound: () => boolean
}

const copilotRoundInjectionKey: InjectionKey<CopilotRoundContext> = Symbol('copilot-round')

/** Read the round a markdown element belongs to, or `null` when not rendered inside a copilot round. */
export function useCopilotRound(): CopilotRoundContext | null {
return inject(copilotRoundInjectionKey, null)
}

export function provideCopilotRound(ctx: CopilotRoundContext) {
return provide(copilotRoundInjectionKey, ctx)
}
11 changes: 11 additions & 0 deletions spx-gui/src/components/copilot/copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ export class Round {
get state() {
return this.stateRef.value
}

/**
* Whether this round was produced live in the current session (vs. loaded from history). Set when the
* round is started; rounds restored via `load` stay `false`. Used by features (e.g. in-editor code
* guides) to decide whether to auto-drive the editor — so a restored suggestion doesn't re-pop guides.
*/
private liveRef = ref(false)
get isLive() {
return this.liveRef.value
}
private setState(state: RoundState) {
this.stateRef.value = state
this.updatedAt = dayjs().valueOf()
Expand Down Expand Up @@ -355,6 +365,7 @@ export class Round {
this.errorRef.value = null
this.apiExceptionCode = null
this.apiExceptionMeta = null
this.liveRef.value = true
this.setState(RoundState.Loading)
this.ctrl = new AbortController()
this.generateCopilotMessage()
Expand Down
Loading