Add user defined system message
This commit is contained in:
@@ -12,7 +12,7 @@ llm:
|
|||||||
url: "http://localhost:8081/v1"
|
url: "http://localhost:8081/v1"
|
||||||
key: ${ODIDERE_LLM_KEY}
|
key: ${ODIDERE_LLM_KEY}
|
||||||
model: "default"
|
model: "default"
|
||||||
system_prompt: "You are a helpful voice assistant. Be concise."
|
system_message: "You are a helpful voice assistant. Be concise."
|
||||||
timeout: "5m"
|
timeout: "5m"
|
||||||
|
|
||||||
tts:
|
tts:
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ type Config struct {
|
|||||||
Key string `yaml:"key"`
|
Key string `yaml:"key"`
|
||||||
// Model is the model identifier.
|
// Model is the model identifier.
|
||||||
Model string `yaml:"model"`
|
Model string `yaml:"model"`
|
||||||
// SystemPrompt is prepended to all conversations.
|
// SystemMessage is prepended to all conversations.
|
||||||
SystemPrompt string `yaml:"system_prompt"`
|
SystemMessage string `yaml:"system_message"`
|
||||||
// Timeout is the maximum duration for a query (e.g., "5m").
|
// Timeout is the maximum duration for a query (e.g., "5m").
|
||||||
// Defaults to 5 minutes if empty.
|
// Defaults to 5 minutes if empty.
|
||||||
Timeout string `yaml:"timeout"`
|
Timeout string `yaml:"timeout"`
|
||||||
@@ -49,13 +49,13 @@ func (cfg Config) Validate() error {
|
|||||||
|
|
||||||
// Client wraps an OpenAI-compatible client with tool execution support.
|
// Client wraps an OpenAI-compatible client with tool execution support.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
client *openai.Client
|
client *openai.Client
|
||||||
log *slog.Logger
|
log *slog.Logger
|
||||||
model string
|
model string
|
||||||
registry *tool.Registry
|
registry *tool.Registry
|
||||||
systemPrompt string
|
systemMessage string
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
tools []openai.Tool
|
tools []openai.Tool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new LLM client with the provided configuration.
|
// NewClient creates a new LLM client with the provided configuration.
|
||||||
@@ -70,10 +70,10 @@ func NewClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
llm := &Client{
|
llm := &Client{
|
||||||
log: log,
|
log: log,
|
||||||
model: cfg.Model,
|
model: cfg.Model,
|
||||||
systemPrompt: cfg.SystemPrompt,
|
systemMessage: cfg.SystemMessage,
|
||||||
registry: registry,
|
registry: registry,
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Timeout == "" {
|
if cfg.Timeout == "" {
|
||||||
@@ -122,12 +122,14 @@ func (c *Client) DefaultModel() string {
|
|||||||
|
|
||||||
// Query sends messages to the LLM using the specified model.
|
// Query sends messages to the LLM using the specified model.
|
||||||
// If model is empty, uses the default configured model.
|
// If model is empty, uses the default configured model.
|
||||||
|
// If systemMessage is non-empty, it overrides the configured system message.
|
||||||
// Returns all messages generated during the query, including tool calls
|
// Returns all messages generated during the query, including tool calls
|
||||||
// and tool results. The final message is the last element in the slice.
|
// and tool results. The final message is the last element in the slice.
|
||||||
func (c *Client) Query(
|
func (c *Client) Query(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
messages []openai.ChatCompletionMessage,
|
messages []openai.ChatCompletionMessage,
|
||||||
model string,
|
model string,
|
||||||
|
systemMessage string,
|
||||||
) ([]openai.ChatCompletionMessage, error) {
|
) ([]openai.ChatCompletionMessage, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, c.timeout)
|
ctx, cancel := context.WithTimeout(ctx, c.timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -137,13 +139,19 @@ func (c *Client) Query(
|
|||||||
model = c.model
|
model = c.model
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend system prompt, if configured and not already present.
|
// Use per-request system message if provided, otherwise fall back to config.
|
||||||
if c.systemPrompt != "" && (len(messages) == 0 ||
|
effectiveMessage := c.systemMessage
|
||||||
|
if systemMessage != "" {
|
||||||
|
effectiveMessage = systemMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend system message, if configured and not already present.
|
||||||
|
if effectiveMessage != "" && (len(messages) == 0 ||
|
||||||
messages[0].Role != openai.ChatMessageRoleSystem) {
|
messages[0].Role != openai.ChatMessageRoleSystem) {
|
||||||
messages = append(
|
messages = append(
|
||||||
[]openai.ChatCompletionMessage{{
|
[]openai.ChatCompletionMessage{{
|
||||||
Role: openai.ChatMessageRoleSystem,
|
Role: openai.ChatMessageRoleSystem,
|
||||||
Content: c.systemPrompt,
|
Content: effectiveMessage,
|
||||||
}},
|
}},
|
||||||
messages...,
|
messages...,
|
||||||
)
|
)
|
||||||
@@ -239,11 +247,13 @@ type StreamEvent struct {
|
|||||||
// streams results. Each complete message (assistant reply, tool call,
|
// streams results. Each complete message (assistant reply, tool call,
|
||||||
// tool result) is sent to the events channel as it becomes available.
|
// tool result) is sent to the events channel as it becomes available.
|
||||||
// The channel is closed before returning.
|
// The channel is closed before returning.
|
||||||
|
// If systemMessage is non-empty, it overrides the configured system message.
|
||||||
// Returns all messages generated during the query.
|
// Returns all messages generated during the query.
|
||||||
func (c *Client) QueryStream(
|
func (c *Client) QueryStream(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
messages []openai.ChatCompletionMessage,
|
messages []openai.ChatCompletionMessage,
|
||||||
model string,
|
model string,
|
||||||
|
systemMessage string,
|
||||||
events chan<- StreamEvent,
|
events chan<- StreamEvent,
|
||||||
) error {
|
) error {
|
||||||
defer close(events)
|
defer close(events)
|
||||||
@@ -256,13 +266,19 @@ func (c *Client) QueryStream(
|
|||||||
model = c.model
|
model = c.model
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend system prompt, if configured and not already present.
|
// Use per-request system message if provided, otherwise fall back to config.
|
||||||
if c.systemPrompt != "" && (len(messages) == 0 ||
|
effectiveMessage := c.systemMessage
|
||||||
|
if systemMessage != "" {
|
||||||
|
effectiveMessage = systemMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend system message, if configured and not already present.
|
||||||
|
if effectiveMessage != "" && (len(messages) == 0 ||
|
||||||
messages[0].Role != openai.ChatMessageRoleSystem) {
|
messages[0].Role != openai.ChatMessageRoleSystem) {
|
||||||
messages = append(
|
messages = append(
|
||||||
[]openai.ChatCompletionMessage{{
|
[]openai.ChatCompletionMessage{{
|
||||||
Role: openai.ChatMessageRoleSystem,
|
Role: openai.ChatMessageRoleSystem,
|
||||||
Content: c.systemPrompt,
|
Content: effectiveMessage,
|
||||||
}},
|
}},
|
||||||
messages...,
|
messages...,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ func TestConfigValidate(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "valid full config",
|
name: "valid full config",
|
||||||
cfg: Config{
|
cfg: Config{
|
||||||
Key: "sk-test-key",
|
Key: "sk-test-key",
|
||||||
Model: "test-model",
|
Model: "test-model",
|
||||||
SystemPrompt: "You are a helpful assistant.",
|
SystemMessage: "You are a helpful assistant.",
|
||||||
Timeout: "30m",
|
Timeout: "30m",
|
||||||
URL: "http://localhost:8080",
|
URL: "http://localhost:8080",
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@@ -121,11 +121,11 @@ func TestNewClient(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "valid config with all fields",
|
name: "valid config with all fields",
|
||||||
cfg: Config{
|
cfg: Config{
|
||||||
Key: "test-key",
|
Key: "test-key",
|
||||||
Model: "test-model",
|
Model: "test-model",
|
||||||
SystemPrompt: "Test prompt",
|
SystemMessage: "Test message",
|
||||||
Timeout: "5m",
|
Timeout: "5m",
|
||||||
URL: "http://localhost:8080",
|
URL: "http://localhost:8080",
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ type Request struct {
|
|||||||
Messages []openai.ChatCompletionMessage `json:"messages"`
|
Messages []openai.ChatCompletionMessage `json:"messages"`
|
||||||
// Model is the LLM model ID. If empty, the default model is used.
|
// Model is the LLM model ID. If empty, the default model is used.
|
||||||
Model string `json:"model,omitempty"`
|
Model string `json:"model,omitempty"`
|
||||||
|
// SystemMessage overrides the configured system message for this request.
|
||||||
|
SystemMessage string `json:"system_message,omitempty"`
|
||||||
// Voice is the voice ID for TTS.
|
// Voice is the voice ID for TTS.
|
||||||
Voice string `json:"voice,omitempty"`
|
Voice string `json:"voice,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -455,7 +457,7 @@ func (svc *Service) voice(w http.ResponseWriter, r *http.Request) {
|
|||||||
if model == "" {
|
if model == "" {
|
||||||
model = svc.llm.DefaultModel()
|
model = svc.llm.DefaultModel()
|
||||||
}
|
}
|
||||||
msgs, err := svc.llm.Query(ctx, messages, model)
|
msgs, err := svc.llm.Query(ctx, messages, model, req.SystemMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorContext(
|
log.ErrorContext(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -731,7 +733,7 @@ func (svc *Service) voiceStream(w http.ResponseWriter, r *http.Request) {
|
|||||||
llmErr error
|
llmErr error
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
llmErr = svc.llm.QueryStream(ctx, messages, model, events)
|
llmErr = svc.llm.QueryStream(ctx, messages, model, req.SystemMessage, events)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Consume events and send as SSE.
|
// Consume events and send as SSE.
|
||||||
|
|||||||
@@ -90,4 +90,9 @@
|
|||||||
<path d="m15 9-6 6"/>
|
<path d="m15 9-6 6"/>
|
||||||
<path d="m9 9 6 6"/>
|
<path d="m9 9 6 6"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="settings" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
|
||||||
|
<circle cx="12" cy="12" r="3"/>
|
||||||
|
</symbol>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.9 KiB |
@@ -593,6 +593,201 @@ body {
|
|||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==================== */
|
||||||
|
/* Settings Modal */
|
||||||
|
/* ==================== */
|
||||||
|
|
||||||
|
.settings-overlay {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1000;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: var(--s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-overlay.open {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-panel {
|
||||||
|
background: var(--color-surface);
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
width: 100%;
|
||||||
|
max-width: 480px;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: var(--s1);
|
||||||
|
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-panel__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: var(--s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-panel__title {
|
||||||
|
font-size: var(--s1);
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close button: remove toolbar border, darken the X. */
|
||||||
|
#settings-close {
|
||||||
|
border: none;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
#settings-close:hover {
|
||||||
|
border-color: transparent;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
|
.settings-tabs {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 2px solid var(--color-border-light);
|
||||||
|
margin-bottom: var(--s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tab {
|
||||||
|
padding: var(--s-2) var(--s-1);
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
margin-bottom: -2px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: var(--s-1);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.settings-tab:hover {
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tab:focus-visible {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tab.active {
|
||||||
|
color: var(--color-text);
|
||||||
|
border-bottom-color: var(--color-primary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tab panels */
|
||||||
|
.settings-tab-panel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tab-panel.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-label {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--s-1);
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text);
|
||||||
|
margin-bottom: var(--s-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-select {
|
||||||
|
width: 100%;
|
||||||
|
height: var(--s2);
|
||||||
|
padding: 0 var(--s-1);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: var(--s-1);
|
||||||
|
line-height: var(--s2);
|
||||||
|
color: var(--color-text);
|
||||||
|
background: var(--color-surface);
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: var(--s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-select:focus-visible {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-textarea {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
min-height: calc(var(--s2) * 6);
|
||||||
|
padding: var(--s-1);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: var(--s-1);
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--color-text);
|
||||||
|
background: var(--color-bg);
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
resize: vertical;
|
||||||
|
margin-bottom: var(--s-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-textarea:focus {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-save-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-save-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: var(--s-2) var(--s-1);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: var(--s-1);
|
||||||
|
font-weight: 500;
|
||||||
|
color: white;
|
||||||
|
background: var(--color-primary);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.15s ease;
|
||||||
|
min-width: var(--s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.settings-save-btn:hover {
|
||||||
|
background: var(--color-primary-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-save-btn:focus-visible {
|
||||||
|
outline: 2px solid var(--color-primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-save-btn--success {
|
||||||
|
background: var(--color-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-save-btn .icon {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* ==================== */
|
/* ==================== */
|
||||||
/* Animations */
|
/* Animations */
|
||||||
/* ==================== */
|
/* ==================== */
|
||||||
@@ -668,4 +863,16 @@ body {
|
|||||||
max-width: 128px;
|
max-width: 128px;
|
||||||
font-size: var(--s-1);
|
font-size: var(--s-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-overlay {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-panel {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100dvh;
|
||||||
|
height: 100dvh;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const ICONS_URL = '/static/icons.svg';
|
|||||||
const MODELS_ENDPOINT = '/v1/models';
|
const MODELS_ENDPOINT = '/v1/models';
|
||||||
const MODEL_KEY = 'odidere_model';
|
const MODEL_KEY = 'odidere_model';
|
||||||
const STORAGE_KEY = 'odidere_history';
|
const STORAGE_KEY = 'odidere_history';
|
||||||
|
const SYSTEM_MESSAGE_KEY = 'odidere_system_message';
|
||||||
const VOICES_ENDPOINT = '/v1/voices';
|
const VOICES_ENDPOINT = '/v1/voices';
|
||||||
const VOICE_KEY = 'odidere_voice';
|
const VOICE_KEY = 'odidere_voice';
|
||||||
|
|
||||||
@@ -42,6 +43,15 @@ class Odidere {
|
|||||||
this.$voice = document.getElementById('voice');
|
this.$voice = document.getElementById('voice');
|
||||||
this.$mute = document.getElementById('mute');
|
this.$mute = document.getElementById('mute');
|
||||||
|
|
||||||
|
// Settings modal
|
||||||
|
this.$settings = document.getElementById('settings');
|
||||||
|
this.$settingsOverlay = document.getElementById('settings-overlay');
|
||||||
|
this.$settingsClose = document.getElementById('settings-close');
|
||||||
|
this.$settingsTabs = document.querySelectorAll('.settings-tab');
|
||||||
|
this.$settingsPanels = document.querySelectorAll('.settings-tab-panel');
|
||||||
|
this.$systemMessageInput = document.getElementById('system-message-input');
|
||||||
|
this.$saveSystemMessage = document.getElementById('save-system-message');
|
||||||
|
|
||||||
// Templates
|
// Templates
|
||||||
this.$tplAssistantMessage = document.getElementById(
|
this.$tplAssistantMessage = document.getElementById(
|
||||||
'tpl-assistant-message',
|
'tpl-assistant-message',
|
||||||
@@ -151,6 +161,28 @@ class Odidere {
|
|||||||
});
|
});
|
||||||
// Mute button
|
// Mute button
|
||||||
this.$mute.addEventListener('click', () => this.#toggleMute());
|
this.$mute.addEventListener('click', () => this.#toggleMute());
|
||||||
|
|
||||||
|
// Settings modal
|
||||||
|
this.$settings.addEventListener('click', () => this.openSettings());
|
||||||
|
this.$settingsClose.addEventListener('click', () => this.closeSettings());
|
||||||
|
this.$settingsOverlay.addEventListener('click', (e) => {
|
||||||
|
if (e.target === this.$settingsOverlay) this.closeSettings();
|
||||||
|
});
|
||||||
|
this.document.addEventListener('keydown', (e) => {
|
||||||
|
if (
|
||||||
|
e.key === 'Escape' &&
|
||||||
|
this.$settingsOverlay.classList.contains('open')
|
||||||
|
) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.closeSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.$settingsTabs.forEach(($tab) => {
|
||||||
|
$tab.addEventListener('click', () => this.#switchTab($tab.dataset.tab));
|
||||||
|
});
|
||||||
|
this.$saveSystemMessage.addEventListener('click', () =>
|
||||||
|
this.#saveSystemMessage(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -557,6 +589,10 @@ class Odidere {
|
|||||||
voice: this.$voice.value,
|
voice: this.$voice.value,
|
||||||
model: this.$model.value,
|
model: this.$model.value,
|
||||||
};
|
};
|
||||||
|
const systemMessage = localStorage.getItem(SYSTEM_MESSAGE_KEY);
|
||||||
|
if (systemMessage) {
|
||||||
|
payload.system_message = systemMessage;
|
||||||
|
}
|
||||||
if (audio) {
|
if (audio) {
|
||||||
payload.audio = await this.#toBase64(audio);
|
payload.audio = await this.#toBase64(audio);
|
||||||
}
|
}
|
||||||
@@ -674,7 +710,11 @@ class Odidere {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Collect tool results and render once all have arrived.
|
// Collect tool results and render once all have arrived.
|
||||||
if (message.role === 'tool' && pendingTools && pendingTools.assistant) {
|
if (
|
||||||
|
message.role === 'tool' &&
|
||||||
|
pendingTools &&
|
||||||
|
pendingTools.assistant
|
||||||
|
) {
|
||||||
pendingTools.results.push(message);
|
pendingTools.results.push(message);
|
||||||
// Add to history (server needs it) but don't render yet.
|
// Add to history (server needs it) but don't render yet.
|
||||||
this.#appendHistory([message]);
|
this.#appendHistory([message]);
|
||||||
@@ -849,6 +889,67 @@ class Odidere {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* openSettings opens the settings modal and loads current values.
|
||||||
|
*/
|
||||||
|
openSettings() {
|
||||||
|
this.$settingsOverlay.classList.add('open');
|
||||||
|
this.#loadSystemMessage();
|
||||||
|
this.#switchTab('model-voice');
|
||||||
|
// Focus the close button for accessibility.
|
||||||
|
this.$settingsClose.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* closeSettings closes the settings modal and restores focus.
|
||||||
|
*/
|
||||||
|
closeSettings() {
|
||||||
|
this.$settingsOverlay.classList.remove('open');
|
||||||
|
this.$settings.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #switchTab switches the active tab in the settings modal.
|
||||||
|
* @param {string} tabName
|
||||||
|
*/
|
||||||
|
#switchTab(tabName) {
|
||||||
|
this.$settingsTabs.forEach(($tab) => {
|
||||||
|
const isActive = $tab.dataset.tab === tabName;
|
||||||
|
$tab.classList.toggle('active', isActive);
|
||||||
|
$tab.setAttribute('aria-selected', String(isActive));
|
||||||
|
});
|
||||||
|
this.$settingsPanels.forEach(($panel) => {
|
||||||
|
const isActive = $panel.dataset.tabPanel === tabName;
|
||||||
|
$panel.classList.toggle('active', isActive);
|
||||||
|
$panel.hidden = !isActive;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #saveSystemMessage saves the textarea value to localStorage.
|
||||||
|
*/
|
||||||
|
#saveSystemMessage() {
|
||||||
|
const value = this.$systemMessageInput.value;
|
||||||
|
localStorage.setItem(SYSTEM_MESSAGE_KEY, value);
|
||||||
|
|
||||||
|
// Brief visual feedback on the save button.
|
||||||
|
this.$saveSystemMessage.replaceChildren(this.#icon('check'));
|
||||||
|
this.$saveSystemMessage.classList.add('settings-save-btn--success');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$saveSystemMessage.textContent = 'Save';
|
||||||
|
this.$saveSystemMessage.classList.remove('settings-save-btn--success');
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #loadSystemMessage reads from localStorage and populates the textarea.
|
||||||
|
*/
|
||||||
|
#loadSystemMessage() {
|
||||||
|
const stored = localStorage.getItem(SYSTEM_MESSAGE_KEY);
|
||||||
|
this.$systemMessageInput.value = stored || '';
|
||||||
|
}
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
// RENDER: SELECTS
|
// RENDER: SELECTS
|
||||||
// ====================
|
// ====================
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
<body>
|
<body>
|
||||||
{{ template "main" . }}
|
{{ template "main" . }}
|
||||||
{{ template "templates" . }}
|
{{ template "templates" . }}
|
||||||
|
{{ template "modal/settings" . }}
|
||||||
</body>
|
</body>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
{{ define "footer/toolbar" }}
|
{{ define "footer/toolbar" }}
|
||||||
<div class="footer__toolbar">
|
<div class="footer__toolbar">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="footer__toolbar-btn"
|
||||||
|
id="settings"
|
||||||
|
aria-label="Settings"
|
||||||
|
>
|
||||||
|
<svg class="icon"><use href="/static/icons.svg#settings"></use></svg>
|
||||||
|
</button>
|
||||||
|
<div class="footer__toolbar-spacer"></div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="footer__toolbar-btn"
|
class="footer__toolbar-btn"
|
||||||
@@ -8,17 +17,6 @@
|
|||||||
>
|
>
|
||||||
<svg class="icon"><use href="/static/icons.svg#reset"></use></svg>
|
<svg class="icon"><use href="/static/icons.svg#reset"></use></svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="footer__toolbar-spacer"></div>
|
|
||||||
<select id="model" class="footer__select" aria-label="Model">
|
|
||||||
<option value="" disabled selected>
|
|
||||||
Loading...
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<select id="voice" class="footer__select" aria-label="Voice">
|
|
||||||
<option value="" disabled selected>
|
|
||||||
Loading...
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="footer__toolbar-btn"
|
class="footer__toolbar-btn"
|
||||||
|
|||||||
83
internal/service/templates/static/modal/settings.gohtml
Normal file
83
internal/service/templates/static/modal/settings.gohtml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{{ define "modal/settings" }}
|
||||||
|
<div class="settings-overlay" id="settings-overlay">
|
||||||
|
<div class="settings-panel" role="dialog" aria-modal="true"
|
||||||
|
aria-labelledby="settings-title">
|
||||||
|
<div class="settings-panel__header">
|
||||||
|
<h2 class="settings-panel__title" id="settings-title">Settings</h2>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="footer__toolbar-btn"
|
||||||
|
id="settings-close"
|
||||||
|
aria-label="Close settings"
|
||||||
|
>
|
||||||
|
<svg class="icon"><use href="/static/icons.svg#close"></use></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-tabs" role="tablist">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="settings-tab active"
|
||||||
|
role="tab"
|
||||||
|
data-tab="model-voice"
|
||||||
|
aria-selected="true"
|
||||||
|
aria-controls="panel-model-voice"
|
||||||
|
>Model & Voice</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="settings-tab"
|
||||||
|
role="tab"
|
||||||
|
data-tab="system-message"
|
||||||
|
aria-selected="false"
|
||||||
|
aria-controls="panel-system-message"
|
||||||
|
>System Message</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-tab-panels">
|
||||||
|
<div
|
||||||
|
class="settings-tab-panel active"
|
||||||
|
role="tabpanel"
|
||||||
|
data-tab-panel="model-voice"
|
||||||
|
id="panel-model-voice"
|
||||||
|
aria-labelledby="tab-model-voice"
|
||||||
|
>
|
||||||
|
<label class="settings-label" for="model">Model</label>
|
||||||
|
<select id="model" class="settings-select" aria-label="Model">
|
||||||
|
<option value="" disabled selected>Loading...</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label class="settings-label" for="voice">Voice</label>
|
||||||
|
<select id="voice" class="settings-select" aria-label="Voice">
|
||||||
|
<option value="" disabled selected>Loading...</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="settings-tab-panel"
|
||||||
|
role="tabpanel"
|
||||||
|
data-tab-panel="system-message"
|
||||||
|
id="panel-system-message"
|
||||||
|
aria-labelledby="tab-system-message"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<label class="settings-label" for="system-message-input">
|
||||||
|
System Message
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="system-message-input"
|
||||||
|
class="settings-textarea"
|
||||||
|
rows="8"
|
||||||
|
placeholder="Enter system message..."
|
||||||
|
></textarea>
|
||||||
|
<div class="settings-save-row">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="settings-save-btn"
|
||||||
|
id="save-system-message"
|
||||||
|
>Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
4
vendor/github.com/google/uuid/dce.go
generated
vendored
4
vendor/github.com/google/uuid/dce.go
generated
vendored
@@ -42,7 +42,7 @@ func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
|
|||||||
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
|
||||||
// domain with the id returned by os.Getuid.
|
// domain with the id returned by os.Getuid.
|
||||||
//
|
//
|
||||||
// NewDCESecurity(Person, uint32(os.Getuid()))
|
// NewDCESecurity(Person, uint32(os.Getuid()))
|
||||||
func NewDCEPerson() (UUID, error) {
|
func NewDCEPerson() (UUID, error) {
|
||||||
return NewDCESecurity(Person, uint32(os.Getuid()))
|
return NewDCESecurity(Person, uint32(os.Getuid()))
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ func NewDCEPerson() (UUID, error) {
|
|||||||
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
|
||||||
// domain with the id returned by os.Getgid.
|
// domain with the id returned by os.Getgid.
|
||||||
//
|
//
|
||||||
// NewDCESecurity(Group, uint32(os.Getgid()))
|
// NewDCESecurity(Group, uint32(os.Getgid()))
|
||||||
func NewDCEGroup() (UUID, error) {
|
func NewDCEGroup() (UUID, error) {
|
||||||
return NewDCESecurity(Group, uint32(os.Getgid()))
|
return NewDCESecurity(Group, uint32(os.Getgid()))
|
||||||
}
|
}
|
||||||
|
|||||||
4
vendor/github.com/google/uuid/hash.go
generated
vendored
4
vendor/github.com/google/uuid/hash.go
generated
vendored
@@ -45,7 +45,7 @@ func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
|
|||||||
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
// NewMD5 returns a new MD5 (Version 3) UUID based on the
|
||||||
// supplied name space and data. It is the same as calling:
|
// supplied name space and data. It is the same as calling:
|
||||||
//
|
//
|
||||||
// NewHash(md5.New(), space, data, 3)
|
// NewHash(md5.New(), space, data, 3)
|
||||||
func NewMD5(space UUID, data []byte) UUID {
|
func NewMD5(space UUID, data []byte) UUID {
|
||||||
return NewHash(md5.New(), space, data, 3)
|
return NewHash(md5.New(), space, data, 3)
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func NewMD5(space UUID, data []byte) UUID {
|
|||||||
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
|
||||||
// supplied name space and data. It is the same as calling:
|
// supplied name space and data. It is the same as calling:
|
||||||
//
|
//
|
||||||
// NewHash(sha1.New(), space, data, 5)
|
// NewHash(sha1.New(), space, data, 5)
|
||||||
func NewSHA1(space UUID, data []byte) UUID {
|
func NewSHA1(space UUID, data []byte) UUID {
|
||||||
return NewHash(sha1.New(), space, data, 5)
|
return NewHash(sha1.New(), space, data, 5)
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/google/uuid/node_js.go
generated
vendored
1
vendor/github.com/google/uuid/node_js.go
generated
vendored
@@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build js
|
||||||
// +build js
|
// +build js
|
||||||
|
|
||||||
package uuid
|
package uuid
|
||||||
|
|||||||
1
vendor/github.com/google/uuid/node_net.go
generated
vendored
1
vendor/github.com/google/uuid/node_net.go
generated
vendored
@@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !js
|
||||||
// +build !js
|
// +build !js
|
||||||
|
|
||||||
package uuid
|
package uuid
|
||||||
|
|||||||
17
vendor/github.com/google/uuid/null.go
generated
vendored
17
vendor/github.com/google/uuid/null.go
generated
vendored
@@ -17,15 +17,14 @@ var jsonNull = []byte("null")
|
|||||||
// NullUUID implements the SQL driver.Scanner interface so
|
// NullUUID implements the SQL driver.Scanner interface so
|
||||||
// it can be used as a scan destination:
|
// it can be used as a scan destination:
|
||||||
//
|
//
|
||||||
// var u uuid.NullUUID
|
// var u uuid.NullUUID
|
||||||
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
|
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
|
||||||
// ...
|
// ...
|
||||||
// if u.Valid {
|
// if u.Valid {
|
||||||
// // use u.UUID
|
// // use u.UUID
|
||||||
// } else {
|
// } else {
|
||||||
// // NULL value
|
// // NULL value
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
type NullUUID struct {
|
type NullUUID struct {
|
||||||
UUID UUID
|
UUID UUID
|
||||||
Valid bool // Valid is true if UUID is not NULL
|
Valid bool // Valid is true if UUID is not NULL
|
||||||
|
|||||||
10
vendor/github.com/google/uuid/uuid.go
generated
vendored
10
vendor/github.com/google/uuid/uuid.go
generated
vendored
@@ -187,10 +187,12 @@ func Must(uuid UUID, err error) UUID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
|
// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
|
||||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
//
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||||
|
//
|
||||||
// It returns an error if the format is invalid, otherwise nil.
|
// It returns an error if the format is invalid, otherwise nil.
|
||||||
func Validate(s string) error {
|
func Validate(s string) error {
|
||||||
switch len(s) {
|
switch len(s) {
|
||||||
|
|||||||
14
vendor/github.com/google/uuid/version4.go
generated
vendored
14
vendor/github.com/google/uuid/version4.go
generated
vendored
@@ -9,7 +9,7 @@ import "io"
|
|||||||
// New creates a new random UUID or panics. New is equivalent to
|
// New creates a new random UUID or panics. New is equivalent to
|
||||||
// the expression
|
// the expression
|
||||||
//
|
//
|
||||||
// uuid.Must(uuid.NewRandom())
|
// uuid.Must(uuid.NewRandom())
|
||||||
func New() UUID {
|
func New() UUID {
|
||||||
return Must(NewRandom())
|
return Must(NewRandom())
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ func New() UUID {
|
|||||||
// NewString creates a new random UUID and returns it as a string or panics.
|
// NewString creates a new random UUID and returns it as a string or panics.
|
||||||
// NewString is equivalent to the expression
|
// NewString is equivalent to the expression
|
||||||
//
|
//
|
||||||
// uuid.New().String()
|
// uuid.New().String()
|
||||||
func NewString() string {
|
func NewString() string {
|
||||||
return Must(NewRandom()).String()
|
return Must(NewRandom()).String()
|
||||||
}
|
}
|
||||||
@@ -31,11 +31,11 @@ func NewString() string {
|
|||||||
//
|
//
|
||||||
// A note about uniqueness derived from the UUID Wikipedia entry:
|
// A note about uniqueness derived from the UUID Wikipedia entry:
|
||||||
//
|
//
|
||||||
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
|
||||||
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
// hit by a meteorite is estimated to be one chance in 17 billion, that
|
||||||
// means the probability is about 0.00000000006 (6 × 10−11),
|
// means the probability is about 0.00000000006 (6 × 10−11),
|
||||||
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
|
||||||
// year and having one duplicate.
|
// year and having one duplicate.
|
||||||
func NewRandom() (UUID, error) {
|
func NewRandom() (UUID, error) {
|
||||||
if !poolEnabled {
|
if !poolEnabled {
|
||||||
return NewRandomFromReader(rander)
|
return NewRandomFromReader(rander)
|
||||||
|
|||||||
8
vendor/gopkg.in/yaml.v3/apic.go
generated
vendored
8
vendor/gopkg.in/yaml.v3/apic.go
generated
vendored
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) 2011-2019 Canonical Ltd
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
// Copyright (c) 2006-2010 Kirill Simonov
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
// the Software without restriction, including without limitation the rights to
|
// the Software without restriction, including without limitation the rights to
|
||||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
// so, subject to the following conditions:
|
// so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
// copies or substantial portions of the Software.
|
// copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
|||||||
9
vendor/gopkg.in/yaml.v3/emitterc.go
generated
vendored
9
vendor/gopkg.in/yaml.v3/emitterc.go
generated
vendored
@@ -162,10 +162,9 @@ func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
|
|||||||
// Check if we need to accumulate more events before emitting.
|
// Check if we need to accumulate more events before emitting.
|
||||||
//
|
//
|
||||||
// We accumulate extra
|
// We accumulate extra
|
||||||
// - 1 event for DOCUMENT-START
|
// - 1 event for DOCUMENT-START
|
||||||
// - 2 events for SEQUENCE-START
|
// - 2 events for SEQUENCE-START
|
||||||
// - 3 events for MAPPING-START
|
// - 3 events for MAPPING-START
|
||||||
//
|
|
||||||
func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
|
func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
|
||||||
if emitter.events_head == len(emitter.events) {
|
if emitter.events_head == len(emitter.events) {
|
||||||
return true
|
return true
|
||||||
@@ -241,7 +240,7 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool
|
|||||||
emitter.indent += 2
|
emitter.indent += 2
|
||||||
} else {
|
} else {
|
||||||
// Everything else aligns to the chosen indentation.
|
// Everything else aligns to the chosen indentation.
|
||||||
emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
|
emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
142
vendor/gopkg.in/yaml.v3/parserc.go
generated
vendored
142
vendor/gopkg.in/yaml.v3/parserc.go
generated
vendored
@@ -227,7 +227,8 @@ func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool
|
|||||||
|
|
||||||
// Parse the production:
|
// Parse the production:
|
||||||
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
||||||
// ************
|
//
|
||||||
|
// ************
|
||||||
func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -249,9 +250,12 @@ func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t)
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// implicit_document ::= block_node DOCUMENT-END*
|
// implicit_document ::= block_node DOCUMENT-END*
|
||||||
// *
|
//
|
||||||
|
// *
|
||||||
|
//
|
||||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||||
// *************************
|
//
|
||||||
|
// *************************
|
||||||
func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
|
func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
|
||||||
|
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
@@ -356,8 +360,8 @@ func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||||
// ***********
|
|
||||||
//
|
//
|
||||||
|
// ***********
|
||||||
func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -379,9 +383,10 @@ func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// implicit_document ::= block_node DOCUMENT-END*
|
// implicit_document ::= block_node DOCUMENT-END*
|
||||||
// *************
|
|
||||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
|
||||||
//
|
//
|
||||||
|
// *************
|
||||||
|
//
|
||||||
|
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||||
func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -428,30 +433,41 @@ func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t)
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// block_node_or_indentless_sequence ::=
|
// block_node_or_indentless_sequence ::=
|
||||||
// ALIAS
|
//
|
||||||
// *****
|
// ALIAS
|
||||||
// | properties (block_content | indentless_block_sequence)?
|
// *****
|
||||||
// ********** *
|
// | properties (block_content | indentless_block_sequence)?
|
||||||
// | block_content | indentless_block_sequence
|
// ********** *
|
||||||
// *
|
// | block_content | indentless_block_sequence
|
||||||
|
// *
|
||||||
|
//
|
||||||
// block_node ::= ALIAS
|
// block_node ::= ALIAS
|
||||||
// *****
|
//
|
||||||
// | properties block_content?
|
// *****
|
||||||
// ********** *
|
// | properties block_content?
|
||||||
// | block_content
|
// ********** *
|
||||||
// *
|
// | block_content
|
||||||
|
// *
|
||||||
|
//
|
||||||
// flow_node ::= ALIAS
|
// flow_node ::= ALIAS
|
||||||
// *****
|
//
|
||||||
// | properties flow_content?
|
// *****
|
||||||
// ********** *
|
// | properties flow_content?
|
||||||
// | flow_content
|
// ********** *
|
||||||
// *
|
// | flow_content
|
||||||
|
// *
|
||||||
|
//
|
||||||
// properties ::= TAG ANCHOR? | ANCHOR TAG?
|
// properties ::= TAG ANCHOR? | ANCHOR TAG?
|
||||||
// *************************
|
//
|
||||||
|
// *************************
|
||||||
|
//
|
||||||
// block_content ::= block_collection | flow_collection | SCALAR
|
// block_content ::= block_collection | flow_collection | SCALAR
|
||||||
// ******
|
//
|
||||||
|
// ******
|
||||||
|
//
|
||||||
// flow_content ::= flow_collection | SCALAR
|
// flow_content ::= flow_collection | SCALAR
|
||||||
// ******
|
//
|
||||||
|
// ******
|
||||||
func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
|
func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
|
||||||
//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
|
//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
|
||||||
|
|
||||||
@@ -682,8 +698,8 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
|
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
|
||||||
// ******************** *********** * *********
|
|
||||||
//
|
//
|
||||||
|
// ******************** *********** * *********
|
||||||
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
@@ -740,7 +756,8 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
||||||
// *********** *
|
//
|
||||||
|
// *********** *
|
||||||
func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -805,14 +822,14 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// block_mapping ::= BLOCK-MAPPING_START
|
// block_mapping ::= BLOCK-MAPPING_START
|
||||||
// *******************
|
|
||||||
// ((KEY block_node_or_indentless_sequence?)?
|
|
||||||
// *** *
|
|
||||||
// (VALUE block_node_or_indentless_sequence?)?)*
|
|
||||||
//
|
//
|
||||||
// BLOCK-END
|
// *******************
|
||||||
// *********
|
// ((KEY block_node_or_indentless_sequence?)?
|
||||||
|
// *** *
|
||||||
|
// (VALUE block_node_or_indentless_sequence?)?)*
|
||||||
//
|
//
|
||||||
|
// BLOCK-END
|
||||||
|
// *********
|
||||||
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
@@ -881,13 +898,11 @@ func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_even
|
|||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// block_mapping ::= BLOCK-MAPPING_START
|
// block_mapping ::= BLOCK-MAPPING_START
|
||||||
//
|
//
|
||||||
// ((KEY block_node_or_indentless_sequence?)?
|
// ((KEY block_node_or_indentless_sequence?)?
|
||||||
//
|
|
||||||
// (VALUE block_node_or_indentless_sequence?)?)*
|
|
||||||
// ***** *
|
|
||||||
// BLOCK-END
|
|
||||||
//
|
|
||||||
//
|
//
|
||||||
|
// (VALUE block_node_or_indentless_sequence?)?)*
|
||||||
|
// ***** *
|
||||||
|
// BLOCK-END
|
||||||
func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -915,16 +930,18 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// flow_sequence ::= FLOW-SEQUENCE-START
|
// flow_sequence ::= FLOW-SEQUENCE-START
|
||||||
// *******************
|
|
||||||
// (flow_sequence_entry FLOW-ENTRY)*
|
|
||||||
// * **********
|
|
||||||
// flow_sequence_entry?
|
|
||||||
// *
|
|
||||||
// FLOW-SEQUENCE-END
|
|
||||||
// *****************
|
|
||||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
|
||||||
// *
|
|
||||||
//
|
//
|
||||||
|
// *******************
|
||||||
|
// (flow_sequence_entry FLOW-ENTRY)*
|
||||||
|
// * **********
|
||||||
|
// flow_sequence_entry?
|
||||||
|
// *
|
||||||
|
// FLOW-SEQUENCE-END
|
||||||
|
// *****************
|
||||||
|
//
|
||||||
|
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||||
|
//
|
||||||
|
// *
|
||||||
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
@@ -987,11 +1004,10 @@ func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_ev
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||||
// *** *
|
|
||||||
//
|
//
|
||||||
|
// *** *
|
||||||
func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -1011,8 +1027,8 @@ func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, ev
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||||
// ***** *
|
|
||||||
//
|
//
|
||||||
|
// ***** *
|
||||||
func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -1035,8 +1051,8 @@ func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t,
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||||
// *
|
|
||||||
//
|
//
|
||||||
|
// *
|
||||||
func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
|
func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
@@ -1053,16 +1069,17 @@ func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, ev
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// flow_mapping ::= FLOW-MAPPING-START
|
// flow_mapping ::= FLOW-MAPPING-START
|
||||||
// ******************
|
|
||||||
// (flow_mapping_entry FLOW-ENTRY)*
|
|
||||||
// * **********
|
|
||||||
// flow_mapping_entry?
|
|
||||||
// ******************
|
|
||||||
// FLOW-MAPPING-END
|
|
||||||
// ****************
|
|
||||||
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
|
||||||
// * *** *
|
|
||||||
//
|
//
|
||||||
|
// ******************
|
||||||
|
// (flow_mapping_entry FLOW-ENTRY)*
|
||||||
|
// * **********
|
||||||
|
// flow_mapping_entry?
|
||||||
|
// ******************
|
||||||
|
// FLOW-MAPPING-END
|
||||||
|
// ****************
|
||||||
|
//
|
||||||
|
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||||
|
// - *** *
|
||||||
func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
@@ -1128,8 +1145,7 @@ func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event
|
|||||||
|
|
||||||
// Parse the productions:
|
// Parse the productions:
|
||||||
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||||
// * ***** *
|
// - ***** *
|
||||||
//
|
|
||||||
func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
|
func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
|
|||||||
8
vendor/gopkg.in/yaml.v3/readerc.go
generated
vendored
8
vendor/gopkg.in/yaml.v3/readerc.go
generated
vendored
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) 2011-2019 Canonical Ltd
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
// Copyright (c) 2006-2010 Kirill Simonov
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
// the Software without restriction, including without limitation the rights to
|
// the Software without restriction, including without limitation the rights to
|
||||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
// so, subject to the following conditions:
|
// so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
// copies or substantial portions of the Software.
|
// copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
|||||||
42
vendor/gopkg.in/yaml.v3/scannerc.go
generated
vendored
42
vendor/gopkg.in/yaml.v3/scannerc.go
generated
vendored
@@ -1614,11 +1614,11 @@ func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
|
|||||||
// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
|
// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
|
||||||
//
|
//
|
||||||
// Scope:
|
// Scope:
|
||||||
// %YAML 1.1 # a comment \n
|
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
// %TAG !yaml! tag:yaml.org,2002: \n
|
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
//
|
//
|
||||||
|
// %YAML 1.1 # a comment \n
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
// %TAG !yaml! tag:yaml.org,2002: \n
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
|
func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
|
||||||
// Eat '%'.
|
// Eat '%'.
|
||||||
start_mark := parser.mark
|
start_mark := parser.mark
|
||||||
@@ -1719,11 +1719,11 @@ func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool
|
|||||||
// Scan the directive name.
|
// Scan the directive name.
|
||||||
//
|
//
|
||||||
// Scope:
|
// Scope:
|
||||||
// %YAML 1.1 # a comment \n
|
|
||||||
// ^^^^
|
|
||||||
// %TAG !yaml! tag:yaml.org,2002: \n
|
|
||||||
// ^^^
|
|
||||||
//
|
//
|
||||||
|
// %YAML 1.1 # a comment \n
|
||||||
|
// ^^^^
|
||||||
|
// %TAG !yaml! tag:yaml.org,2002: \n
|
||||||
|
// ^^^
|
||||||
func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
|
func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
|
||||||
// Consume the directive name.
|
// Consume the directive name.
|
||||||
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
||||||
@@ -1758,8 +1758,9 @@ func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark
|
|||||||
// Scan the value of VERSION-DIRECTIVE.
|
// Scan the value of VERSION-DIRECTIVE.
|
||||||
//
|
//
|
||||||
// Scope:
|
// Scope:
|
||||||
// %YAML 1.1 # a comment \n
|
//
|
||||||
// ^^^^^^
|
// %YAML 1.1 # a comment \n
|
||||||
|
// ^^^^^^
|
||||||
func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
|
func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
|
||||||
// Eat whitespaces.
|
// Eat whitespaces.
|
||||||
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
||||||
@@ -1797,10 +1798,11 @@ const max_number_length = 2
|
|||||||
// Scan the version number of VERSION-DIRECTIVE.
|
// Scan the version number of VERSION-DIRECTIVE.
|
||||||
//
|
//
|
||||||
// Scope:
|
// Scope:
|
||||||
// %YAML 1.1 # a comment \n
|
//
|
||||||
// ^
|
// %YAML 1.1 # a comment \n
|
||||||
// %YAML 1.1 # a comment \n
|
// ^
|
||||||
// ^
|
// %YAML 1.1 # a comment \n
|
||||||
|
// ^
|
||||||
func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
|
func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
|
||||||
|
|
||||||
// Repeat while the next character is digit.
|
// Repeat while the next character is digit.
|
||||||
@@ -1834,9 +1836,9 @@ func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark
|
|||||||
// Scan the value of a TAG-DIRECTIVE token.
|
// Scan the value of a TAG-DIRECTIVE token.
|
||||||
//
|
//
|
||||||
// Scope:
|
// Scope:
|
||||||
// %TAG !yaml! tag:yaml.org,2002: \n
|
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
//
|
//
|
||||||
|
// %TAG !yaml! tag:yaml.org,2002: \n
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
|
func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
|
||||||
var handle_value, prefix_value []byte
|
var handle_value, prefix_value []byte
|
||||||
|
|
||||||
@@ -2847,7 +2849,7 @@ func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if parser.buffer[parser.buffer_pos+peek] == '#' {
|
if parser.buffer[parser.buffer_pos+peek] == '#' {
|
||||||
seen := parser.mark.index+peek
|
seen := parser.mark.index + peek
|
||||||
for {
|
for {
|
||||||
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
||||||
return false
|
return false
|
||||||
@@ -2876,7 +2878,7 @@ func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t
|
|||||||
parser.comments = append(parser.comments, yaml_comment_t{
|
parser.comments = append(parser.comments, yaml_comment_t{
|
||||||
token_mark: token_mark,
|
token_mark: token_mark,
|
||||||
start_mark: start_mark,
|
start_mark: start_mark,
|
||||||
line: text,
|
line: text,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -2910,7 +2912,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
|
|||||||
// the foot is the line below it.
|
// the foot is the line below it.
|
||||||
var foot_line = -1
|
var foot_line = -1
|
||||||
if scan_mark.line > 0 {
|
if scan_mark.line > 0 {
|
||||||
foot_line = parser.mark.line-parser.newlines+1
|
foot_line = parser.mark.line - parser.newlines + 1
|
||||||
if parser.newlines == 0 && parser.mark.column > 1 {
|
if parser.newlines == 0 && parser.mark.column > 1 {
|
||||||
foot_line++
|
foot_line++
|
||||||
}
|
}
|
||||||
@@ -2996,7 +2998,7 @@ func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) boo
|
|||||||
recent_empty = false
|
recent_empty = false
|
||||||
|
|
||||||
// Consume until after the consumed comment line.
|
// Consume until after the consumed comment line.
|
||||||
seen := parser.mark.index+peek
|
seen := parser.mark.index + peek
|
||||||
for {
|
for {
|
||||||
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
8
vendor/gopkg.in/yaml.v3/writerc.go
generated
vendored
8
vendor/gopkg.in/yaml.v3/writerc.go
generated
vendored
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) 2011-2019 Canonical Ltd
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
// Copyright (c) 2006-2010 Kirill Simonov
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
// the Software without restriction, including without limitation the rights to
|
// the Software without restriction, including without limitation the rights to
|
||||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
// so, subject to the following conditions:
|
// so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
// copies or substantial portions of the Software.
|
// copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
|||||||
75
vendor/gopkg.in/yaml.v3/yaml.go
generated
vendored
75
vendor/gopkg.in/yaml.v3/yaml.go
generated
vendored
@@ -17,8 +17,7 @@
|
|||||||
//
|
//
|
||||||
// Source code and other details for the project are available at GitHub:
|
// Source code and other details for the project are available at GitHub:
|
||||||
//
|
//
|
||||||
// https://github.com/go-yaml/yaml
|
// https://github.com/go-yaml/yaml
|
||||||
//
|
|
||||||
package yaml
|
package yaml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -75,16 +74,15 @@ type Marshaler interface {
|
|||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
//
|
//
|
||||||
// type T struct {
|
// type T struct {
|
||||||
// F int `yaml:"a,omitempty"`
|
// F int `yaml:"a,omitempty"`
|
||||||
// B int
|
// B int
|
||||||
// }
|
// }
|
||||||
// var t T
|
// var t T
|
||||||
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||||
//
|
//
|
||||||
// See the documentation of Marshal for the format of tags and a list of
|
// See the documentation of Marshal for the format of tags and a list of
|
||||||
// supported tag options.
|
// supported tag options.
|
||||||
//
|
|
||||||
func Unmarshal(in []byte, out interface{}) (err error) {
|
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||||
return unmarshal(in, out, false)
|
return unmarshal(in, out, false)
|
||||||
}
|
}
|
||||||
@@ -185,36 +183,35 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
|
|||||||
//
|
//
|
||||||
// The field tag format accepted is:
|
// The field tag format accepted is:
|
||||||
//
|
//
|
||||||
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||||
//
|
//
|
||||||
// The following flags are currently supported:
|
// The following flags are currently supported:
|
||||||
//
|
//
|
||||||
// omitempty Only include the field if it's not set to the zero
|
// omitempty Only include the field if it's not set to the zero
|
||||||
// value for the type or to empty slices or maps.
|
// value for the type or to empty slices or maps.
|
||||||
// Zero valued structs will be omitted if all their public
|
// Zero valued structs will be omitted if all their public
|
||||||
// fields are zero, unless they implement an IsZero
|
// fields are zero, unless they implement an IsZero
|
||||||
// method (see the IsZeroer interface type), in which
|
// method (see the IsZeroer interface type), in which
|
||||||
// case the field will be excluded if IsZero returns true.
|
// case the field will be excluded if IsZero returns true.
|
||||||
//
|
//
|
||||||
// flow Marshal using a flow style (useful for structs,
|
// flow Marshal using a flow style (useful for structs,
|
||||||
// sequences and maps).
|
// sequences and maps).
|
||||||
//
|
//
|
||||||
// inline Inline the field, which must be a struct or a map,
|
// inline Inline the field, which must be a struct or a map,
|
||||||
// causing all of its fields or keys to be processed as if
|
// causing all of its fields or keys to be processed as if
|
||||||
// they were part of the outer struct. For maps, keys must
|
// they were part of the outer struct. For maps, keys must
|
||||||
// not conflict with the yaml keys of other struct fields.
|
// not conflict with the yaml keys of other struct fields.
|
||||||
//
|
//
|
||||||
// In addition, if the key is "-", the field is ignored.
|
// In addition, if the key is "-", the field is ignored.
|
||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
//
|
//
|
||||||
// type T struct {
|
// type T struct {
|
||||||
// F int `yaml:"a,omitempty"`
|
// F int `yaml:"a,omitempty"`
|
||||||
// B int
|
// B int
|
||||||
// }
|
// }
|
||||||
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||||
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||||
//
|
|
||||||
func Marshal(in interface{}) (out []byte, err error) {
|
func Marshal(in interface{}) (out []byte, err error) {
|
||||||
defer handleErr(&err)
|
defer handleErr(&err)
|
||||||
e := newEncoder()
|
e := newEncoder()
|
||||||
@@ -358,22 +355,21 @@ const (
|
|||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
//
|
//
|
||||||
// var person struct {
|
// var person struct {
|
||||||
// Name string
|
// Name string
|
||||||
// Address yaml.Node
|
// Address yaml.Node
|
||||||
// }
|
// }
|
||||||
// err := yaml.Unmarshal(data, &person)
|
// err := yaml.Unmarshal(data, &person)
|
||||||
//
|
//
|
||||||
// Or by itself:
|
// Or by itself:
|
||||||
//
|
//
|
||||||
// var person Node
|
// var person Node
|
||||||
// err := yaml.Unmarshal(data, &person)
|
// err := yaml.Unmarshal(data, &person)
|
||||||
//
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
// Kind defines whether the node is a document, a mapping, a sequence,
|
// Kind defines whether the node is a document, a mapping, a sequence,
|
||||||
// a scalar value, or an alias to another node. The specific data type of
|
// a scalar value, or an alias to another node. The specific data type of
|
||||||
// scalar nodes may be obtained via the ShortTag and LongTag methods.
|
// scalar nodes may be obtained via the ShortTag and LongTag methods.
|
||||||
Kind Kind
|
Kind Kind
|
||||||
|
|
||||||
// Style allows customizing the apperance of the node in the tree.
|
// Style allows customizing the apperance of the node in the tree.
|
||||||
Style Style
|
Style Style
|
||||||
@@ -421,7 +417,6 @@ func (n *Node) IsZero() bool {
|
|||||||
n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
|
n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LongTag returns the long form of the tag that indicates the data type for
|
// LongTag returns the long form of the tag that indicates the data type for
|
||||||
// the node. If the Tag field isn't explicitly defined, one will be computed
|
// the node. If the Tag field isn't explicitly defined, one will be computed
|
||||||
// based on the node properties.
|
// based on the node properties.
|
||||||
|
|||||||
10
vendor/gopkg.in/yaml.v3/yamlh.go
generated
vendored
10
vendor/gopkg.in/yaml.v3/yamlh.go
generated
vendored
@@ -438,7 +438,9 @@ type yaml_document_t struct {
|
|||||||
// The number of written bytes should be set to the size_read variable.
|
// The number of written bytes should be set to the size_read variable.
|
||||||
//
|
//
|
||||||
// [in,out] data A pointer to an application data specified by
|
// [in,out] data A pointer to an application data specified by
|
||||||
// yaml_parser_set_input().
|
//
|
||||||
|
// yaml_parser_set_input().
|
||||||
|
//
|
||||||
// [out] buffer The buffer to write the data from the source.
|
// [out] buffer The buffer to write the data from the source.
|
||||||
// [in] size The size of the buffer.
|
// [in] size The size of the buffer.
|
||||||
// [out] size_read The actual number of bytes read from the source.
|
// [out] size_read The actual number of bytes read from the source.
|
||||||
@@ -639,7 +641,6 @@ type yaml_parser_t struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type yaml_comment_t struct {
|
type yaml_comment_t struct {
|
||||||
|
|
||||||
scan_mark yaml_mark_t // Position where scanning for comments started
|
scan_mark yaml_mark_t // Position where scanning for comments started
|
||||||
token_mark yaml_mark_t // Position after which tokens will be associated with this comment
|
token_mark yaml_mark_t // Position after which tokens will be associated with this comment
|
||||||
start_mark yaml_mark_t // Position of '#' comment mark
|
start_mark yaml_mark_t // Position of '#' comment mark
|
||||||
@@ -659,13 +660,14 @@ type yaml_comment_t struct {
|
|||||||
// @a buffer to the output.
|
// @a buffer to the output.
|
||||||
//
|
//
|
||||||
// @param[in,out] data A pointer to an application data specified by
|
// @param[in,out] data A pointer to an application data specified by
|
||||||
// yaml_emitter_set_output().
|
//
|
||||||
|
// yaml_emitter_set_output().
|
||||||
|
//
|
||||||
// @param[in] buffer The buffer with bytes to be written.
|
// @param[in] buffer The buffer with bytes to be written.
|
||||||
// @param[in] size The size of the buffer.
|
// @param[in] size The size of the buffer.
|
||||||
//
|
//
|
||||||
// @returns On success, the handler should return @c 1. If the handler failed,
|
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||||
// the returned value should be @c 0.
|
// the returned value should be @c 0.
|
||||||
//
|
|
||||||
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||||
|
|
||||||
type yaml_emitter_state_t int
|
type yaml_emitter_state_t int
|
||||||
|
|||||||
20
vendor/gopkg.in/yaml.v3/yamlprivateh.go
generated
vendored
20
vendor/gopkg.in/yaml.v3/yamlprivateh.go
generated
vendored
@@ -1,17 +1,17 @@
|
|||||||
//
|
//
|
||||||
// Copyright (c) 2011-2019 Canonical Ltd
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
// Copyright (c) 2006-2010 Kirill Simonov
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
// this software and associated documentation files (the "Software"), to deal in
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
// the Software without restriction, including without limitation the rights to
|
// the Software without restriction, including without limitation the rights to
|
||||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
// of the Software, and to permit persons to whom the Software is furnished to do
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
// so, subject to the following conditions:
|
// so, subject to the following conditions:
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
// copies or substantial portions of the Software.
|
// copies or substantial portions of the Software.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
@@ -137,8 +137,8 @@ func is_crlf(b []byte, i int) bool {
|
|||||||
func is_breakz(b []byte, i int) bool {
|
func is_breakz(b []byte, i int) bool {
|
||||||
//return is_break(b, i) || is_z(b, i)
|
//return is_break(b, i) || is_z(b, i)
|
||||||
return (
|
return (
|
||||||
// is_break:
|
// is_break:
|
||||||
b[i] == '\r' || // CR (#xD)
|
b[i] == '\r' || // CR (#xD)
|
||||||
b[i] == '\n' || // LF (#xA)
|
b[i] == '\n' || // LF (#xA)
|
||||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
@@ -151,8 +151,8 @@ func is_breakz(b []byte, i int) bool {
|
|||||||
func is_spacez(b []byte, i int) bool {
|
func is_spacez(b []byte, i int) bool {
|
||||||
//return is_space(b, i) || is_breakz(b, i)
|
//return is_space(b, i) || is_breakz(b, i)
|
||||||
return (
|
return (
|
||||||
// is_space:
|
// is_space:
|
||||||
b[i] == ' ' ||
|
b[i] == ' ' ||
|
||||||
// is_breakz:
|
// is_breakz:
|
||||||
b[i] == '\r' || // CR (#xD)
|
b[i] == '\r' || // CR (#xD)
|
||||||
b[i] == '\n' || // LF (#xA)
|
b[i] == '\n' || // LF (#xA)
|
||||||
@@ -166,8 +166,8 @@ func is_spacez(b []byte, i int) bool {
|
|||||||
func is_blankz(b []byte, i int) bool {
|
func is_blankz(b []byte, i int) bool {
|
||||||
//return is_blank(b, i) || is_breakz(b, i)
|
//return is_blank(b, i) || is_breakz(b, i)
|
||||||
return (
|
return (
|
||||||
// is_blank:
|
// is_blank:
|
||||||
b[i] == ' ' || b[i] == '\t' ||
|
b[i] == ' ' || b[i] == '\t' ||
|
||||||
// is_breakz:
|
// is_breakz:
|
||||||
b[i] == '\r' || // CR (#xD)
|
b[i] == '\r' || // CR (#xD)
|
||||||
b[i] == '\n' || // LF (#xA)
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
|||||||
Reference in New Issue
Block a user