Continue AI features and improve protocol support

This commit is contained in:
2026-02-15 16:57:32 +00:00
parent ab91c7dba1
commit 9a70f86088
62 changed files with 5472 additions and 441 deletions

View File

@@ -7,7 +7,54 @@
<p class="is-size-7">{{ plan.objective }}</p>
{% endif %}
</div>
<span class="tag is-light">{{ plan.creation_mode|title }}</span>
<div class="is-flex is-flex-direction-column" style="gap: 0.35rem;">
<span class="tag is-light">{{ plan.creation_mode|title }} / {{ plan.status|title }}</span>
<span class="tag is-light">Created {{ plan.created_at }}</span>
<span class="tag is-light">Updated {{ plan.updated_at }}</span>
{% if plan.source_ai_result_id %}
<span class="tag is-light">Source Result {{ plan.source_ai_result_id }}</span>
{% endif %}
<form
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'ai_workspace_mitigation_meta_save' type='widget' person_id=person.id plan_id=plan.id %}"
hx-target="#mitigation-shell-{{ person.id }}"
hx-swap="outerHTML">
<input type="hidden" name="active_tab" value="{{ active_tab|default:'plan_board' }}">
<div class="field" style="margin-bottom: 0.3rem;">
<div class="control">
<input class="input is-small" type="text" name="title" value="{{ plan.title }}" placeholder="Plan title">
</div>
</div>
<div class="field" style="margin-bottom: 0.3rem;">
<div class="control">
<textarea class="textarea is-small" rows="2" name="objective" placeholder="Plan objective">{{ plan.objective }}</textarea>
</div>
</div>
<div class="field is-grouped is-grouped-right" style="margin: 0; gap: 0.3rem;">
<div class="control">
<div class="select is-small">
<select name="creation_mode">
{% for value, label in plan_creation_mode_choices %}
<option value="{{ value }}" {% if plan.creation_mode == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control">
<div class="select is-small">
<select name="status">
{% for value, label in plan_status_choices %}
<option value="{{ value }}" {% if plan.status == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control">
<button type="submit" class="button is-small is-light">Save</button>
</div>
</div>
</form>
</div>
</div>
{% if notice_message %}
@@ -84,6 +131,7 @@
{% for rule in rules %}
<article class="box" style="padding: 0.55rem; margin-bottom: 0.45rem; border: 1px solid rgba(0, 0, 0, 0.12); box-shadow: none;">
<span class="tag is-light is-small" style="margin-bottom: 0.3rem;">Rule</span>
<span class="tag is-light is-small" style="margin-bottom: 0.3rem;">Created {{ rule.created_at }}</span>
<form
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'ai_workspace_mitigation_artifact_save' type='widget' person_id=person.id plan_id=plan.id kind='rule' artifact_id=rule.id %}"
@@ -95,7 +143,10 @@
<div class="field" style="margin-bottom: 0.35rem;">
<textarea class="textarea is-small" rows="3" name="body" data-editable="1" readonly>{{ rule.content }}</textarea>
</div>
<input type="hidden" name="enabled" value="1">
<label class="checkbox is-size-7" style="margin-bottom: 0.35rem;">
<input type="checkbox" name="enabled" value="1" {% if rule.enabled %}checked{% endif %}>
Enabled
</label>
<input type="hidden" name="active_tab" value="{{ active_tab|default:'plan_board' }}">
<div class="buttons are-small" style="margin: 0;">
<button type="button" class="button is-link is-light" data-edit-state="view" onclick="giaMitigationToggleEdit(this); return false;">Edit</button>
@@ -136,6 +187,7 @@
{% for game in games %}
<article class="box" style="padding: 0.55rem; margin-bottom: 0.45rem; border: 1px solid rgba(0, 0, 0, 0.12); box-shadow: none;">
<span class="tag is-light is-small" style="margin-bottom: 0.3rem;">Game</span>
<span class="tag is-light is-small" style="margin-bottom: 0.3rem;">Created {{ game.created_at }}</span>
<form
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'ai_workspace_mitigation_artifact_save' type='widget' person_id=person.id plan_id=plan.id kind='game' artifact_id=game.id %}"
@@ -147,7 +199,10 @@
<div class="field" style="margin-bottom: 0.35rem;">
<textarea class="textarea is-small" rows="3" name="body" data-editable="1" readonly>{{ game.instructions }}</textarea>
</div>
<input type="hidden" name="enabled" value="1">
<label class="checkbox is-size-7" style="margin-bottom: 0.35rem;">
<input type="checkbox" name="enabled" value="1" {% if game.enabled %}checked{% endif %}>
Enabled
</label>
<input type="hidden" name="active_tab" value="{{ active_tab|default:'plan_board' }}">
<div class="buttons are-small" style="margin: 0;">
<button type="button" class="button is-link is-light" data-edit-state="view" onclick="giaMitigationToggleEdit(this); return false;">Edit</button>
@@ -203,6 +258,7 @@
{% for correction in corrections %}
<article class="box" style="padding: 0.55rem; margin-bottom: 0.5rem; border: 1px solid rgba(0, 0, 0, 0.12); box-shadow: none;">
<span class="tag is-light is-small" style="margin-bottom: 0.3rem;">Correction</span>
<span class="tag is-light is-small" style="margin-bottom: 0.3rem;">Created {{ correction.created_at }}</span>
<form
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-post="{% url 'ai_workspace_mitigation_artifact_save' type='widget' person_id=person.id plan_id=plan.id kind='correction' artifact_id=correction.id %}"
@@ -220,8 +276,41 @@
<label class="label is-small" style="margin-bottom: 0.2rem;">Insight</label>
<textarea class="textarea is-small" rows="2" name="body">{{ correction.clarification }}</textarea>
</div>
<div class="column is-12-mobile is-4-tablet" style="padding: 0.3rem;">
<label class="label is-small" style="margin-bottom: 0.2rem;">Perspective</label>
<div class="select is-small is-fullwidth">
<select name="perspective">
{% for value, label in correction.PERSPECTIVE_CHOICES %}
<option value="{{ value }}" {% if correction.perspective == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="column is-12-mobile is-4-tablet" style="padding: 0.3rem;">
<label class="label is-small" style="margin-bottom: 0.2rem;">Share Target</label>
<div class="select is-small is-fullwidth">
<select name="share_target">
{% for value, label in correction.SHARE_TARGET_CHOICES %}
<option value="{{ value }}" {% if correction.share_target == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="column is-12-mobile is-4-tablet" style="padding: 0.3rem;">
<label class="label is-small" style="margin-bottom: 0.2rem;">Language Style</label>
<div class="select is-small is-fullwidth">
<select name="language_style">
{% for value, label in correction.LANGUAGE_STYLE_CHOICES %}
<option value="{{ value }}" {% if correction.language_style == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<input type="hidden" name="enabled" value="1">
<label class="checkbox is-size-7" style="margin-bottom: 0.35rem;">
<input type="checkbox" name="enabled" value="1" {% if correction.enabled %}checked{% endif %}>
Enabled
</label>
<input type="hidden" name="active_tab" value="{{ active_tab|default:'corrections' }}">
<div class="buttons are-small" style="margin: 0;">
<button class="button is-small is-link is-light">Save Correction</button>
@@ -395,6 +484,12 @@
<p class="is-size-7" style="margin-bottom: 0;">
Last run: {% if auto_settings.last_run_at %}{{ auto_settings.last_run_at }}{% else %}Never{% endif %}
</p>
<p class="is-size-7" style="margin-bottom: 0;">
Created: {{ auto_settings.created_at }} | Updated: {{ auto_settings.updated_at }}
</p>
<p class="is-size-7" style="margin-bottom: 0;">
Last checked event ts: {{ auto_settings.last_checked_event_ts|default:"None" }}
</p>
{% if auto_settings.last_result_summary %}
<p class="is-size-7" style="margin-top: 0.35rem; margin-bottom: 0;">{{ auto_settings.last_result_summary }}</p>
{% endif %}
@@ -463,10 +558,9 @@
<label class="label is-small" style="margin-bottom: 0.25rem;">Bundle</label>
<div class="select is-small">
<select name="artifact_type">
<option value="rulebook">Rulebook</option>
<option value="rules">Rules</option>
<option value="games">Games</option>
<option value="corrections">Corrections</option>
{% for value, label in artifact_type_choices %}
<option value="{{ value }}">{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
@@ -474,9 +568,9 @@
<label class="label is-small" style="margin-bottom: 0.25rem;">Format</label>
<div class="select is-small">
<select name="export_format">
<option value="markdown">Markdown</option>
<option value="json">JSON</option>
<option value="text">Text</option>
{% for value, label in artifact_format_choices %}
<option value="{{ value }}">{{ label }}</option>
{% endfor %}
</select>
</div>
</div>
@@ -494,6 +588,11 @@
<p class="is-size-7 has-text-weight-semibold" style="margin-bottom: 0.3rem;">
Last Export: {{ latest_export.artifact_type|title }} ({{ latest_export.export_format|upper }})
</p>
<p class="is-size-7" style="margin-bottom: 0.3rem;">
Created {{ latest_export.created_at }} |
Protocol {{ latest_export.protocol_version }} |
Meta {{ latest_export.meta }}
</p>
<pre style="max-height: 14rem; overflow: auto; margin: 0; white-space: pre-wrap; font-size: 0.72rem; line-height: 1.28;">{{ latest_export.payload }}</pre>
</article>
{% endif %}
@@ -505,6 +604,7 @@
{% for message in mitigation_messages %}
<div style="margin-bottom: 0.45rem;">
<span class="tag is-light is-small">{{ message.role }}</span>
<span class="tag is-light is-small">{{ message.created_at }}</span>
<div style="margin-top: 0.15rem; white-space: pre-wrap;">{{ message.text }}</div>
</div>
{% empty %}
@@ -560,9 +660,9 @@
const forceInput = document.getElementById("engage-force-send-" + pid);
const sendBtn = document.getElementById("engage-send-btn-" + pid);
const force =
!!(window.giaWorkspaceState
&& window.giaWorkspaceState[pid]
&& window.giaWorkspaceState[pid].forceSend);
!!(window.giaWorkspaceState
&& window.giaWorkspaceState[pid]
&& window.giaWorkspaceState[pid].forceSend);
if (forceInput) {
forceInput.value = force ? "1" : "0";
}