Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
05ec441
Add built-in on-device AI support
shai-almog Jul 25, 2026
33b0861
Fix AI source and guide compliance
shai-almog Jul 25, 2026
f576c5c
Fix AI guide prose lint
shai-almog Jul 25, 2026
c89cb9e
Fix iOS inference file loading on Catalyst
shai-almog Jul 25, 2026
987f8fe
Avoid iOS adapter outer captures
shai-almog Jul 25, 2026
65a724e
Satisfy core AI static analysis
shai-almog Jul 25, 2026
7016de9
Exclude optional Android AI sources from port build
shai-almog Jul 25, 2026
6ed61e0
Fix ML Kit builds on Apple Silicon simulators
shai-almog Jul 25, 2026
a448489
Support SIMD fallback on x86 iOS simulators
shai-almog Jul 25, 2026
6fe8457
Add full headers to iOS SIMD sources
shai-almog Jul 25, 2026
7b9b250
Stabilize iOS FAB screenshot comparison
shai-almog Jul 25, 2026
6d709a5
Allow slow Metal benchmark progress
shai-almog Jul 26, 2026
c1f61e4
Allow slow GL simulator benchmark
shai-almog Jul 26, 2026
e78d0c0
Resolve on-device AI review feedback
shai-almog Jul 26, 2026
5d0bcb1
Add required builder test copyright header
shai-almog Jul 26, 2026
d6f3106
Fix on-device AI guide prose checks
shai-almog Jul 26, 2026
ea0fce9
Harden builder archive extraction
shai-almog Jul 26, 2026
2165939
Link Apple Natural Language framework
shai-almog Jul 26, 2026
52b7421
Avoid blocking EDT in vision backend test
shai-almog Jul 26, 2026
f8d1552
Resolve AI backend review comments
shai-almog Jul 26, 2026
6ed7db2
Complete iOS AI fallback and face results
shai-almog Jul 26, 2026
c5f07fb
Harden inference metadata and input mapping
shai-almog Jul 26, 2026
26335fd
Serialize inference lifecycle operations
shai-almog Jul 26, 2026
76d7daf
Normalize pose results across backends
shai-almog Jul 26, 2026
8f15981
Normalize iOS vision result details
shai-almog Jul 26, 2026
bff9439
Fix vision threading and rotated geometry
shai-almog Jul 26, 2026
37dec29
Harden dynamic inference and vision state
shai-almog Jul 26, 2026
5cdca14
Fix Apple Vision barcode detection in simulators
shai-almog Jul 27, 2026
a352e81
Reject insecure model download redirects
shai-almog Jul 27, 2026
d9bd7ea
Resolve remaining AI value and cache races
shai-almog Jul 27, 2026
90b2571
Validate raw vision buffers before allocation
shai-almog Jul 27, 2026
fa9dce5
Preserve inference inputs and label indices
shai-almog Jul 27, 2026
b51442c
Snapshot inference configuration and validate shapes
shai-almog Jul 27, 2026
b645b44
Close cancelled sessions and snapshot language calls
shai-almog Jul 27, 2026
63df084
Snapshot backend options before async work
shai-almog Jul 27, 2026
3419ed2
Avoid array clone in ParparVM snapshots
shai-almog Jul 27, 2026
59b09ec
Preserve iOS barcode payload bytes
shai-almog Jul 27, 2026
382e8ba
Normalize Smart Reply participant IDs
shai-almog Jul 27, 2026
86cc165
Raise iOS target for ML Kit pods
shai-almog Jul 27, 2026
54a9200
Secure model cache downloads and promotion
shai-almog Jul 27, 2026
ebd1a36
Fix Android LiteRT output execution
shai-almog Jul 27, 2026
7b00690
Honor dynamic outputs and strict NPU requests
shai-almog Jul 27, 2026
1ce7829
Fix developer guide prose lint
shai-almog Jul 27, 2026
506f33b
Handle inference cancellation and raw frames
shai-almog Jul 27, 2026
f5efc48
Keep native inference serialized after cancellation
shai-almog Jul 27, 2026
434e782
Guard pending vision work after close
shai-almog Jul 27, 2026
747cecf
Define model download request identity
shai-almog Jul 27, 2026
cda000a
Correct on-device AI documentation
shai-almog Jul 27, 2026
ea0a928
Apply catalog platform requirements
shai-almog Jul 27, 2026
dee5804
Preserve catalog compatibility and plist defaults
shai-almog Jul 27, 2026
770ada0
Allow trusted archive extraction routes
shai-almog Jul 27, 2026
88de186
Reject encoded formats in pixel images
shai-almog Jul 27, 2026
447dacc
Reject overflowing segmentation masks
shai-almog Jul 27, 2026
6b17ebc
Normalize Android translation language tags
shai-almog Jul 27, 2026
66dcd87
Harden inference callbacks and language tags
shai-almog Jul 27, 2026
111d0bd
Preserve encoded vision image rotation
shai-almog Jul 27, 2026
e97371b
Use native byte order for LiteRT outputs
shai-almog Jul 27, 2026
f9b4cbd
Isolate inference and model cache concurrency
shai-almog Jul 27, 2026
2c5ecaa
Satisfy developer guide prose checks
shai-almog Jul 27, 2026
49d8c08
Reject NaN AI confidence thresholds
shai-almog Jul 27, 2026
a248696
Guard microphone recording on tvOS
shai-almog Jul 27, 2026
a28e626
Guard low-level audio unit on watchOS
shai-almog Jul 28, 2026
7be841b
Avoid allocation benchmark hangs on iOS simulator
shai-almog Jul 28, 2026
7f56cc9
Report iOS simulator runtime correctly
shai-almog Jul 28, 2026
9af5456
Scope SIMD registry guard to JavaSE simulator
shai-almog Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
27 changes: 8 additions & 19 deletions .github/workflows/ai-cn1lib-native-check.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
name: AI cn1lib iOS xcodebuild check
name: Large AI cn1lib iOS xcodebuild check

# Per cn1lib: synthesise a tiny Xcode project that links the bundled
# `nativeios/*.m` against the real `GoogleMLKit/*` (or TFLite / whisper)
# pod, run `pod install`, then `xcodebuild build`. Catches API drift,
# missing imports, and missing pod hints early -- on the same macOS
# runners we already use for build-ios.
# The lightweight vision, language, and LiteRT bridges now live in core and
# are exercised by the normal port/build tests. Keep this isolated native
# check for the two deliberately large cn1libs.

on:
workflow_dispatch:
pull_request:
branches: [master]
paths:
- 'maven/cn1-ai-**'
- 'maven/cn1-ai-whisper/**'
- 'maven/cn1-ai-stablediffusion/**'
- 'scripts/gen-ai-cn1libs.py'
- '.github/workflows/ai-cn1lib-native-check.yml'
push:
branches: [master]
paths:
- 'maven/cn1-ai-**'
- 'maven/cn1-ai-whisper/**'
- 'maven/cn1-ai-stablediffusion/**'
- 'scripts/gen-ai-cn1libs.py'

jobs:
Expand All @@ -32,17 +32,6 @@ jobs:
fail-fast: false
matrix:
include:
- { lib: cn1-ai-mlkit-text, pod: 'GoogleMLKit/TextRecognition' }
- { lib: cn1-ai-mlkit-barcode, pod: 'GoogleMLKit/BarcodeScanning' }
- { lib: cn1-ai-mlkit-face, pod: 'GoogleMLKit/FaceDetection' }
- { lib: cn1-ai-mlkit-labeling, pod: 'GoogleMLKit/ImageLabeling' }
- { lib: cn1-ai-mlkit-translate, pod: 'GoogleMLKit/Translate' }
- { lib: cn1-ai-mlkit-smartreply, pod: 'GoogleMLKit/SmartReply' }
- { lib: cn1-ai-mlkit-langid, pod: 'GoogleMLKit/LanguageID' }
- { lib: cn1-ai-mlkit-pose, pod: 'GoogleMLKit/PoseDetection' }
- { lib: cn1-ai-mlkit-segmentation, pod: 'GoogleMLKit/SegmentationSelfie' }
- { lib: cn1-ai-mlkit-docscan, pod: '' } # VisionKit/CoreImage only
- { lib: cn1-ai-tflite, pod: 'TensorFlowLiteObjC' }
- { lib: cn1-ai-whisper, pod: '' } # links static libwhisper.a
- { lib: cn1-ai-stablediffusion, pod: '' } # links Swift runner
steps:
Expand Down
22 changes: 0 additions & 22 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,17 +184,6 @@ jobs:
git config --global --add safe.directory "$GITHUB_WORKSPACE"

all_libs=(
cn1-ai-mlkit-text
cn1-ai-mlkit-barcode
cn1-ai-mlkit-face
cn1-ai-mlkit-labeling
cn1-ai-mlkit-translate
cn1-ai-mlkit-smartreply
cn1-ai-mlkit-langid
cn1-ai-mlkit-pose
cn1-ai-mlkit-segmentation
cn1-ai-mlkit-docscan
cn1-ai-tflite
cn1-ai-whisper
cn1-ai-stablediffusion
cn1-admob
Expand All @@ -203,17 +192,6 @@ jobs:
cn1-ads-mock
)
ai_libs=(
cn1-ai-mlkit-text
cn1-ai-mlkit-barcode
cn1-ai-mlkit-face
cn1-ai-mlkit-labeling
cn1-ai-mlkit-translate
cn1-ai-mlkit-smartreply
cn1-ai-mlkit-langid
cn1-ai-mlkit-pose
cn1-ai-mlkit-segmentation
cn1-ai-mlkit-docscan
cn1-ai-tflite
cn1-ai-whisper
cn1-ai-stablediffusion
)
Expand Down
21 changes: 18 additions & 3 deletions .github/workflows/scripts-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ jobs:
CN1SS_FAIL_ON_MISMATCH: '1'
CN1SS_ALLOWED_MISSING: '0'
CN1SS_PORT_ID: ios-gl
# Google ML Kit excludes arm64 simulators, so this job uses ParparVM's
# x86 path. On a contended runner the allocation benchmark remained
# active after the generic 720s idle limit, with less than three
# minutes left under the 35-minute absolute cap. Keep strict missing-
# screenshot gating, but allow the active benchmark to complete.
CN1SS_SUITE_IDLE_TIMEOUT_SECONDS: '1200'
CN1SS_SUITE_TIMEOUT_SECONDS: '3000'
run: |
set -euo pipefail
mkdir -p "${ARTIFACTS_DIR}"
Expand All @@ -251,9 +258,9 @@ jobs:
"${{ steps.build-ios-app.outputs.workspace }}" \
"" \
"${{ steps.build-ios-app.outputs.scheme }}"
# The script enforces both a 35-minute absolute suite limit and a
# 12-minute no-progress limit. This outer cap also includes its
# native rebuild and cleanup, so it must leave those phases headroom.
# This job uses a 50-minute absolute suite limit and a 20-minute
# no-progress limit. The outer cap also includes its native rebuild
# and cleanup, so it leaves those phases headroom.
timeout-minutes: 65

- name: Upload iOS OpenGL port status
Expand Down Expand Up @@ -464,6 +471,14 @@ jobs:
CN1SS_REPORT_TITLE: 'iOS Metal screenshot updates'
CN1SS_SUCCESS_MESSAGE: '✅ Native iOS Metal screenshot tests passed.'
CN1SS_COMMENT_LOG_PREFIX: '[run-ios-device-tests-metal]'
# The x86 simulator runs CommonWorkloadBenchmarkTest through
# ParparVM's non-NEON path. Its object-allocation block took 555s on
# an otherwise identical successful run, but exceeded the generic
# 720s idle gate on a contended runner while the hang sample showed
# active GC/allocation work. Allow that benchmark variance here;
# the suite's independent 35-minute absolute limit still catches a
# genuinely stuck app.
CN1SS_SUITE_IDLE_TIMEOUT_SECONDS: '1200'
# Strict screenshot gating: fail on any pixel mismatch and on any
# missing screenshot. The Metal backend must produce the full
# baseline set; a test that hangs (e.g. the DialogTheme texture
Expand Down
27 changes: 27 additions & 0 deletions CodenameOne/src/com/codename1/ai/ChatMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,19 @@ public final class ChatMessage {
private final String name;
private final String toolCallId;

/// Creates a message with no assistant tool calls or provider name.
/// @param role speaker role; required
/// @param parts ordered multimodal content; {@code null} becomes empty
public ChatMessage(Role role, List<MessagePart> parts) {
this(role, parts, null, null, null);
}

/// Creates a fully specified normalized message.
/// @param role speaker role; required
/// @param parts ordered content parts; {@code null} becomes empty
/// @param toolCalls assistant tool calls; {@code null} becomes empty
/// @param name optional provider-visible participant name
/// @param toolCallId tool call answered by a {@link Role#TOOL} message
public ChatMessage(Role role, List<MessagePart> parts, List<ToolCall> toolCalls,
String name, String toolCallId) {
if (role == null) {
Expand All @@ -57,20 +66,29 @@ public ChatMessage(Role role, List<MessagePart> parts, List<ToolCall> toolCalls,
this.toolCallId = toolCallId;
}

/// @param text system instruction text
/// @return a single-part system message
public static ChatMessage system(String text) {
return single(Role.SYSTEM, new TextPart(text));
}

/// @param text user input text
/// @return a single-part user message
public static ChatMessage user(String text) {
return single(Role.USER, new TextPart(text));
}

/// @param text assistant output text
/// @return a single-part assistant message
public static ChatMessage assistant(String text) {
return single(Role.ASSISTANT, new TextPart(text));
}

/// Builds a USER message containing both a text and image part --
/// the common multi-modal pattern.
/// @param text optional text accompanying the image
/// @param image image content sent to the model
/// @return multimodal user message
public static ChatMessage userWithImage(String text, ImagePart image) {
List<MessagePart> parts = new ArrayList<MessagePart>(2);
if (text != null && text.length() > 0) {
Expand All @@ -81,6 +99,9 @@ public static ChatMessage userWithImage(String text, ImagePart image) {
}

/// Builds a TOOL message wrapping the result of a previous tool call.
/// @param toolCallId provider id of the answered tool call
/// @param resultJson application result encoded as JSON
/// @return tool-role result message
public static ChatMessage toolResult(String toolCallId, String resultJson) {
return new ChatMessage(Role.TOOL,
Arrays.<MessagePart>asList(new ToolResultPart(toolCallId, resultJson)),
Expand All @@ -93,29 +114,35 @@ private static ChatMessage single(Role r, MessagePart p) {
return new ChatMessage(r, parts);
}

/// @return speaker role
public Role getRole() {
return role;
}

/// @return immutable content parts in message order
public List<MessagePart> getParts() {
return parts;
}

/// @return immutable assistant tool calls
public List<ToolCall> getToolCalls() {
return toolCalls;
}

/// @return optional participant name, or {@code null}
public String getName() {
return name;
}

/// @return answered tool-call id for tool messages, or {@code null}
public String getToolCallId() {
return toolCallId;
}

/// Convenience: concatenates the text of every [TextPart]. Image
/// and tool-result parts are skipped. Useful for `ChatView`
/// rendering when you don't care about multi-modal content.
/// @return text parts joined with newlines
public String getText() {
StringBuilder sb = new StringBuilder();
for (MessagePart p : parts) {
Expand Down
Loading
Loading